{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Text classification and sentiment analysis: Yelp Reviews"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once text data has been converted into numerical features using the natural language processing techniques discussed in the previous sections, text classification works just like any other classification task.\n",
    "\n",
    "In this notebook, we will apply these preprocessing technique to Yelp business reviews to classify them by review scores and sentiment polarity. More specifically, we will apply sentiment analysis to the significantly larger Yelp business review dataset with five outcome classes. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:31:14.252099Z",
     "start_time": "2020-06-20T22:31:14.250089Z"
    }
   },
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:31:15.068766Z",
     "start_time": "2020-06-20T22:31:14.433436Z"
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "from pathlib import Path\n",
    "import json\n",
    "from time import time\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "from scipy import sparse\n",
    "\n",
    "# spacy, textblob and nltk for language processing\n",
    "from textblob import TextBlob\n",
    "\n",
    "# sklearn for feature extraction & modeling\n",
    "from sklearn.feature_extraction.text import CountVectorizer\n",
    "from sklearn.naive_bayes import MultinomialNB\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import accuracy_score, confusion_matrix\n",
    "import joblib\n",
    "\n",
    "import lightgbm as lgb\n",
    "\n",
    "# Visualization\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:31:15.755213Z",
     "start_time": "2020-06-20T22:31:15.751035Z"
    }
   },
   "outputs": [],
   "source": [
    "sns.set_style('white')\n",
    "np.random.seed(42)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Yelp Challenge: business reviews dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Follow the [instructions](../data/create_yelp_review_data.ipynb) to create the dataset. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:31:20.338294Z",
     "start_time": "2020-06-20T22:31:20.336457Z"
    }
   },
   "outputs": [],
   "source": [
    "data_dir = Path('..', 'data', 'yelp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:31:36.050276Z",
     "start_time": "2020-06-20T22:31:22.182112Z"
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "yelp_reviews = pd.read_parquet(data_dir / 'user_reviews.parquet')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:31:37.005166Z",
     "start_time": "2020-06-20T22:31:36.051543Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 8021122 entries, 0 to 8021121\n",
      "Data columns (total 25 columns):\n",
      " #   Column              Non-Null Count    Dtype  \n",
      "---  ------              --------------    -----  \n",
      " 0   stars               8021122 non-null  float64\n",
      " 1   useful              8021122 non-null  int64  \n",
      " 2   funny               8021122 non-null  int64  \n",
      " 3   cool                8021122 non-null  int64  \n",
      " 4   text                8021122 non-null  object \n",
      " 5   year                8021122 non-null  int64  \n",
      " 6   month               8021122 non-null  int64  \n",
      " 7   review_count        8021122 non-null  int64  \n",
      " 8   useful_user         8021122 non-null  int64  \n",
      " 9   funny_user          8021122 non-null  int64  \n",
      " 10  cool_user           8021122 non-null  int64  \n",
      " 11  fans                8021122 non-null  int64  \n",
      " 12  average_stars       8021122 non-null  float64\n",
      " 13  compliment_hot      8021122 non-null  int64  \n",
      " 14  compliment_more     8021122 non-null  int64  \n",
      " 15  compliment_profile  8021122 non-null  int64  \n",
      " 16  compliment_cute     8021122 non-null  int64  \n",
      " 17  compliment_list     8021122 non-null  int64  \n",
      " 18  compliment_note     8021122 non-null  int64  \n",
      " 19  compliment_plain    8021122 non-null  int64  \n",
      " 20  compliment_cool     8021122 non-null  int64  \n",
      " 21  compliment_funny    8021122 non-null  int64  \n",
      " 22  compliment_writer   8021122 non-null  int64  \n",
      " 23  compliment_photos   8021122 non-null  int64  \n",
      " 24  member_yrs          8021122 non-null  int64  \n",
      "dtypes: float64(2), int64(22), object(1)\n",
      "memory usage: 1.6+ GB\n"
     ]
    }
   ],
   "source": [
    "yelp_reviews.info(null_counts=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Explore data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:33:48.280743Z",
     "start_time": "2020-06-20T22:33:48.278310Z"
    }
   },
   "outputs": [],
   "source": [
    "yelp_dir = Path('results', 'yelp')\n",
    "\n",
    "text_features_dir = yelp_dir / 'data'\n",
    "if not text_features_dir.exists():\n",
    "    text_features_dir.mkdir(exist_ok=True, parents=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following figure shows the number of reviews and the average number of stars per year."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Reviews & Stars by Year"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:32:54.666950Z",
     "start_time": "2020-06-20T22:31:41.122337Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABQgAAAEYCAYAAAAQ+RvmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nOzdd3hUVf7H8c+dnh4iCWLoQbAAi13E0CwgRVGEABp7WX+WtQIWYkRpig1csaxYIggKWEBdC+qqiAUVEaUoQpQihJJepp3fH9HRGBDEJJck79fz+Dwz956Z+yHZ5TLfOed8LWOMEQAAAAAAAIBGyWF3AAAAAAAAAAD2oUAIAAAAAAAANGIUCAEAAAAAAIBGjAIhAAAAAAAA0IhRIAQAAAAAAAAaMQqEAAAAAAAAQCNGgRD1WseOHTVo0CCdccYZGjx4sPr27ashQ4bo66+/3uf3vPXWW/XRRx/VYMq6s2zZMv3jH//Qt99+W+X4zJkz1a9fP5WUlNiUDACwL5YtW6bMzEwNGjRIAwcO1CWXXKLvvvsucv6iiy7Sjh07bEwIAGhMLr74Yv3www/y+/3q27fvLsfYee/KzMxUnz59dMYZZ+j000/XaaedpoceeqhGrzFt2jSNGzduj+PGjRunadOm1ei1gdrksjsA8Hc9/fTTSkpKijx/4okndNddd2nOnDn79H7jx4+vqWh1rmvXrrrssss0atQozZ8/Xx6PR+vXr9fUqVP19NNPKyYmxu6IAIC95Pf7dfnll2vGjBk6/PDDJUkvv/yyLr30Ui1atEhOp1OLFy+2OSUAoLEIBoP66aef1K5dO3366afq0qVLtTH7w71r1KhR6tevnySpsLBQ/fv3V7du3XTUUUfV6nWB+o4CIRqUYDCozZs3KyEhIXJs+vTpevPNNxUOh5Wamqrbb79dpaWlGj58uD744AN5PB6FQiH16tVLTz31lLKzs3XOOeeoX79++uKLLzRlyhSVlZXJ4XDoqquuUo8ePdS9e3fNmTNHrVu31qOPPqrZs2fr3XfflSRdcMEFuvDCC1VRUaHp06fLsiw5nU6NGjVKxxxzTJW88+fP13//+1+Fw2Ft2rRJzZo106RJk9SsWTMVFRVp/PjxWrNmjQKBgLp166ZRo0bJ5XKpU6dOOumkk7Rq1SpNmTJFnTt3jrznFVdcoSVLluj+++/XjTfeqFGjRun666/XIYccorVr12r8+PHKz89XKBRSZmamzj77bIXDYU2YMEFfffWVSkpKZIzRXXfdpaOOOkpjxoxRfn6+fvrpJ/Xq1Us33XRT3fwyAaCRKysrU1FRkUpLSyPHTj/9dMXGxioUCum2226TJJ1//vl67LHHtGrVKj366KPy+/3asWOHBg8erGuvvVaffPKJxo8fr+joaJWUlGjWrFm69dZblZubK4fDocMPP1zjxo2Tw1F1YUmfPn00YMAALV68WEVFRbrwwgs1cuRISdI777yj6dOnKxAIyOfzafTo0TriiCM0bdo0LVu2TFu3blXHjh01ZcqUyPtNnz5d33//ve69915J0tKlS3XXXXfppZde2uX9tnfv3iotLVV2drZyc3OVn5+vmJgYTZkyRe3atVNmZqYSEhL0ww8/aMSIEcrMzKztXwkANFqXXnqpfvjhBxUXF+uMM87Qli1bFBMTo5kzZ+qcc86JjLP73vVHv66gatKkiaTKe1uXLl20evVqXX/99erSpYvGjRunzZs3KxAIaMCAAfrnP/8pSXrkkUe0aNEilZeXq6ysTKNHj9Ypp5xS5f2feuopzZ8/X0888YSioqJ06623atWqVUpJSZHT6YwUJb/77juNGzdO+fn5sixLF110kQYPHqwzzjhDY8aMUbdu3bRw4ULdfPPN+uyzz+Tz+XTrrbfq8MMP1/LlyxUbG6vVq1fr559/VseOHTV58mQmf6DmGaAe69Chgxk4cKAZOHCg6d69u+nTp4+58847zbZt24wxxrz44ovm2muvNYFAwBhjzOzZs80ll1xijDHmnHPOMa+//roxxpj33nvPDB8+3BhjzLnnnmtef/11k5+fb0499VTz008/GWOM+fnnn02PHj3Mxo0bzZgxY0xOTk7kfbp3725++OEHU1hYaI477jhTUVFhTjrpJPPll18aY4z54IMPzLRp06rlnzdvnunatav54YcfjDHG3HPPPebqq682xhgzZswY88wzzxhjjAkGg+bGG280jz32WOTP/eKLL+7257Jp0yZz3HHHmVGjRpnrrrvOGGNMIBAw/fv3NytWrDDGGFNYWGhOO+008+WXX5ovvvjCXH311SYUChljjHn00UfN5ZdfbowxZvTo0eb888//C78VAEBNmTFjhunSpYvp06ePufHGG80LL7xgSktLI+c7dOhgtm/fbsLhsDn33HPNunXrjDGV96xDDz3UbN++3Xz88cfmkEMOMRs2bDDGVN4bL7roImNM5f3l1ltvNevXr6927d69e5uxY8eacDhsNm/ebI477jizatUqs27dOjNw4ECzY8cOY4wxa9asMd27dzclJSVm6tSppm/fvpH77u9t27bNHHnkkWbnzp3GGGNuuukm89xzz/3p/fb11183d955Z+Q9xo4da8aNG2eMqbxf33zzzX/3RwwA2EszZ840jzzyiDHGmCuvvNJ88803uxxn573r3HPPNb179zann3666d+/vzn88MPNTTfdZMLhsDGm8t720EMPRcZnZmaaRYsWGWOMKS8vN5mZmebVV181GzZsMJmZmaasrMwYY8zChQvNwIEDjTHGTJ061dxxxx3mscceMxkZGaagoMAYY8z48ePNqFGjTDgcNtu3bzc9evQwU6dONYFAwJx00knmjTfeiPw509PTzRdffGGmTZtmJk2aZIwxZtSoUaZ79+7mgw8+MOFw2HTv3t1s3brVjB492mRkZJiKigrj9/vN4MGDzdy5c//qrw/YI9tmEH711VeaMmWKcnJydjtm/vz5eu655xQKhXTSSSfpyiuvrMOEqC9+XWL8zTff6LLLLtNxxx2nAw44QJL07rvv6uuvv9aQIUMkSeFwWGVlZZKks88+Wy+++KL69eun+fPna9iwYVXed9myZcrLy6vyvzvLsrR69Wqdcsopmj17tgYPHqy8vDwNHDhQH330kRISEpSeni6Px6MBAwboqquuUs+ePdW9e3ddeumlu8zfvXt3tW3bVpI0bNgwnXHGGZKk9957T19//bXmzp0rSSovL6/yuqOPPnq3P5PmzZvrxhtv1H333ac333xTkrR+/Xr9+OOPuuWWWyLjysvL9e2332rkyJFKSEjQ7Nmz9dNPP+mTTz6p8o0U0/EBwB4XXnihhg4dqs8++0yfffaZHn/8cT3++OOaO3eu4uLiIuMsy9Ijjzyi9957TwsXLtTatWtljInc85o3b67U1FRJlX+n33///crMzNQJJ5yg888/X61bt97l9UeOHCnLsnTggQcqPT1dixcvltfr1datW3XBBRdUuf6PP/4oqXK7C5er+j8xDzjgAPXq1Usvv/yyBg8erA8//FC33367li5dutv7bb9+/dSyZUvl5OQoNzdXn376qY444ojIuD+7FwIAataqVat08sknS6qcEde+fftdjrP73vX7JcY7duzQZZddpscee0yXX365pN/uHaWlpfrss89UUFCgBx98MHJs1apV6t+/v+6++24tWLBAubm5kZVWv3rzzTeVl5enRx55RPHx8ZKkJUuW6JZbbpFlWUpKSorMNly/fr0qKip06qmnSpKaNWumU089VR988IH69u2r66+/XqNGjdLSpUt1wQUXaPHixYqJiVGrVq2UnJwsSZHPmJLUoUMHFRQU7P0vDthLthQIH3/8cb3yyiuKiora7Zgff/xRzz33nHJycuTxeDR16lQFAgG53e46TIr65PDDD9fNN9+sMWPG6NBDD1WLFi0UDod1ySWXRJZE+f3+yF+mp512miZNmqS1a9fqs88+06RJk6q8XygUUlpaml544YXIsS1btigpKUnhcFi33Xab/ve//+m4447TCSecoOeee05RUVHq37+/JOm6667TkCFDtHjxYs2fP18zZsyIFPt+z+l0Rh6Hw+HI83A4rAcffFBpaWmSKvfPsCwrMjY6OvpPfx4tW7ZUUlKSYmNjI3+euLg4vfzyy5Ex27ZtU1xcnN577z2NHz9eF154oU466SS1a9dOr7zyyl5fCwBQ8z7//HN9+eWXuuSSS9S7d2/17t1b119/vQYOHKjFixdHPvxIlR9ozjzzTJ188sk6+uijNWTIEL399tsyxkiq+vd4y5Yt9dZbb+mTTz7Rxx9/rAsvvFDjxo1Tnz59qmX4faEvHA7L4XAoHA6rW7dueuCBByLnNm/erJSUFL311lt/es8455xzlJ2dLZfLpVNPPVUxMTF/er+dNWuWnn/+eZ1zzjkaNGiQEhMTtWHDhsg47k8AUDcuvfRSffrpp/riiy909913a8uWLRo6dKiGDRtWZYnx/nDv+r2kpCQNHDhQH374YaRA+Ov7hsNhGWM0e/bsSG1ix44d8nq9+uabb/R///d/uuCCC9S9e3cdc8wxuuOOOyLv27p1a40dO1Z33HGHjjrqqEiR8Nfs0m+f80KhUJXPcb+OCwaD6tixowKBgBYtWqQ2bdqod+/euu666+Ryuao0gfH5fJHHlmVVuQ5QU2zpYtyqVasq3XxWr16tzMxMZWZm6uqrr1ZRUZE++ugjderUSaNHj9a5556rI488kuIg9mjgwIHq0qWLJk6cKEk68cQTNXfuXBUXF0uSHnzwQY0aNUqS5PV6NWDAAI0ZM0annnpqtYJ1165dlZubq88++0yStHLlSvXt21dbtmyR1+vVMccco4ceekjdu3fXscceq2XLlmnp0qVKT09XMBhUnz59VFZWphEjRuj222/X6tWr5ff7q2X++OOPtWXLFknS7Nmz1bt370j2p556SsYY+f1+XXHFFXr22Wf3+WfTtm1b+Xy+SIFw8+bNGjhwoFasWKHFixerd+/eGjlypDp16qS3335boVBon68FAPj7kpKSNH36dC1dujRyLC8vT8XFxerQoYOkyg8fwWBQubm5Ki4u1rXXXqs+ffrok08+kd/vVzgcrva+s2bN0s0336wTTzxRN910k0488UR9++23u8zw0ksvSZI2bdqkxYsXq0ePHurWrZsWL16stWvXSpL+97//6fTTT682031XjjzySDkcDj3xxBMaPny4pD+/33744Yc688wzNXToULVt21bvvPMO9ycAsMEDDzyg1NRULVy4UNdee63OPvtsvfzyy1WKg9L+ce/6vUAgoMWLF++yoUpsbKy6du2qJ598UlLlhIwRI0Zo0aJF+uyzz9SpUyddeOGFOvbYY7Vo0aIq95+OHTuqb9++6tatW6RwmJ6errlz5yocDqugoECLFi2SJLVr104ulyuysmvLli164403dMIJJ0iSTj75ZN17773q3r270tLSVFxcrAULFkRmHAJ1xZYZhH379q3y7e/YsWM1YcIEtW/fXi+88IL+85//yOfzaenSpXruuedUUVGhESNGaO7cuZHKPLA7Y8eO1emnn64PPvhAQ4cO1ZYtWzRs2DBZlqXmzZtXmSk4dOhQPfvss8rOzq72PklJSZo6daruvvtuVVRUyBiju+++Wy1atJAknXLKKXrzzTd1/PHHy+fz6ZBDDlFCQoK8Xq8k6ZZbbtGNN94ol8sly7I0YcKEyLTw32vWrJluuukm5eXlqX379ho3bpwk6dZbb9X48eM1aNAgBQIBnXDCCbrkkkv2+efi8Xj08MMPa/z48frPf/6jYDCof/3rXzrqqKOUmJioG264QYMGDVIwGFT37t0jjV0AAPZo27at/v3vf+v+++/Xzz//LK/Xq7i4OE2YMEHt2rWTJPXr10+ZmZl68MEH1atXL5122mnyeDzq0KGD2rdvr9zc3Gr3nsGDB+vTTz9V//79FRUV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jh2655577I5UIzwuhw5M8KmkYvdNR7r8sg9hYdlv+xC6HI4q+xICAOqvrKws/fjjj+revbs2btyo2267ze5IAIBGhCXGAIB6484779SMGTMkSf3797c5Tc06MN6nnwvKd3u+U2qCJOmbTQXqltZUkuR1OZRfRoEQABqC3NxczZw5U5J08skna/jw4Xt8TSgU0m233aZ169bJ6XRq4sSJatWqVW1HBQA0QMwgBFBjygN/banjXx0PxMXFadGiRVq7dq3WrVundevW2R2pxsT73PK4HAqEwrs836FZnDwuR5Vlxl6XQ8XlQYXD7FcFAPVdRUWFysrKJEnl5eV7tY3Gu+++K0maPXu2rrnmGk2cOLFWMwIAGi5mEAKoMT63U23GvLrX49dPGlCLadAQ7dixQ0899VTkuWVZeuaZZ+wLVIMcDkstEqO0fnupmkR7qp13Ox06rHl8lQKhZVkKh40qgmFFeXbd4AQAUD+cd955OuOMM3TwwQfr+++/1zXXXLPH15x88snq1auXJGnTpk1q2rRpLacEADRUFAgBAPVGTk5Oled+v9+mJLWjaZxXP+SV7PZ8p9QEPftxrgrKAkqIclcetKSyQIgCIQDUc6effrp69Oihn376SS1atFCTJk326nUul0ujR4/WW2+9palTp9ZySgBAQ0WBEABQb8yePVtPPvmkgsGgjDFyu91644037I5VY6I9LiVEu1XqDyraU/0W3eV3+xCe8Ms+hE7LUnF5QEkx1WcdAgDql8TERCUmJv7l102ePFk33nijhg0bpldffVXR0dG1kA4A0JCxByEAoN54/vnnlZOTox49emjixIlKS0vbq9dt375dPXv21Nq1a6scX7hwoYYOHarhw4crKytL4fCu9/+rS6mJUSrbzf6c7VNi5XU59PWG35YZe1wOFZTvvvsxAKDheumll/Too49KkqKiomRZlpxOZpQDAP46CoQAgHqjSZMmSklJUUlJiY477jgVFBTs8TWBQEBZWVny+XxVjpeXl+uBBx7QM888o9mzZ6u4uDiy2budkmI8cliWQrtoPOJ2OnToH/Yh9LqcKij1yxgalQBAffbEE0/85deceuqp+vbbb3XOOefo4osv1i233CKv11sL6QAADR0FQgBAvREXF6e3335blmVp9uzZ2rFjxx5fM3nyZA0fPlwpKSlVjns8Hs2ePVtRUVGS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s+DafV9Am8WC1Wpgsxi7HxsqAoocJNPUfb7la5oUUkT2pgKhiIh0WZFIhOnTp1NUVITVamXWrFnk5eXF13/xxRfcd999mKZJVlYW999/P06nM4kZixye7FYLKR4LKR47uekejuuTRjAUpqE5TDAUwWWzYrdZYkW+VsU+iyYHEfkeqbYue1NxUET2pgKhxB3oJ0j6xElEOru3334bgIULF/LRRx8xa9YsHn30UQBM02TGjBk8/PDD9O3bl7/97W9s376d/Pz8ZKYs0iVYLUast6DLnuxURERERGQ/qEAocS67lX7T/rnf22t4goh0dqeddhpjxowBYMeOHWRmZsbXFRUVkZqayvz581m/fj2jR49WcVBERERERLolTesmIiJdms1mY+rUqdx9992MHz8+vryqqopPP/2USy+9lHnz5vHhhx/ywQcfJDFTERERERGR5FCBUEREurzZs2fz+uuvM2PGDILBIACpqan07duXAQMGYLfbOeWUU1i9enWSMxUREREREfn+qUAoIiJd1ksvvcTcuXMBcLvdGIaB1Rq7d2pubi4NDQ0UFxcDsGLFCgYOHJi0XEVERERERJJF9yA8jGgSERGRAzNu3DhuueUWLrvsMsLhMLfeeitvvPEGwWCQiy++mHvuuYcpU6ZgmibDhg2L369QRERERESkO2m3QBiNRrnzzjtZt24dDoeDmTNn0rdv3/j6xYsX88c//hGbzcb555/PRRdd1KEJd2eaRERE5MB4PB4eeuihNtefdNJJPPfcc99jRiIiIiIiIp1Pu0OM33rrLUKhEIsWLWLKlCncd9998XUtLS3MmjWLJ554ggULFrBo0SLKyso6NGERERERERERERFJnHYLhCtXruSUU04BYOjQoa1u4F5YWEheXh4pKSk4HA6OP/54VqxY0XHZdnJNLZEO3V5ERERERERERCTRDNM0ze/a4LbbbmPcuHGMHj0agDFjxvDWW29hs9lYsWIFTz31FH/4wx8AeOihh8jJyeHCCy9sM96IESPo3bt3Ag9BREQON2lpaTz++OPJTuOg6DomItK96RomIiKHs7auY+3eg9Dn89HQ0BB/HI1Gsdls+1zX0NCA3+//zngfffTRfictIiLS2eg6JiIihytdw0REpC3tDjEePnw4S5YsAeCzzz5j0KBB8XUFBQUUFxdTXV1NKBRixYoVDBs2rOOyFRERERERERERkYRqd4jxnlmM169fj2ma3HvvvXz11VcEg0Euvvji+CzGpmly/vnnc9lll31fuYuIiIiIiIiIiMghardAKCIiIiIiIiIiIl1Xu0OMRUREREREREREpOtSgVBERERERERERKQbU4FQRERERERERESkG7MlY6ctLS3ceuutbN++nVAoxLXXXsuAAQOYNm0ahmEwcOBA7rjjDiwWC88++ywLFy7EZrNx7bXXcuqpp8bjFBYWctFFF7Fs2TKcTmfC4pumyahRo+jXrx8AQ4cOZcqUKQk9hkgkwqxZs1i9ejWhUIjrrruu1bEdavzHHnuM9957D4Da2lrKy8tZunRpwuLX1dVxww030NjYiN1u5/777ycrKyth8aurq7npppuor68nNTWVmTNnkpGRcVDxASorK5kwYQL/+Mc/cDqdNDU1cdNNN1FRUYHX62X27Nmkp6cf9O94X/sAKC4u5le/+hWvvPLKIbWDfcWvq6uLn6OWlhamTZvWahbxQ40fDAaZMmUKNTU1uN1u7r///lbnKBHnJ1HteF/x22vHhxo/kW14X/Hba8OJeg0lqh3vK3577bir6ehrW2fOvb320Jlzb68ddJbc4eCuZZ019/auYZ059z2+77ba0detzpx7MttpV7Fn4sl169bhcDiYOXMmffv2TXZah5XPP/+cBx54gAULFlBcXNzm61f27UD/DkjbIpEI06dPp6ioCKvVyqxZszBNU+fyIFVUVPCzn/2MJ554ApvN1r3Po5kEzz33nDlz5kzTNE2zsrLSHD16tHnNNdeYH374oWmapjljxgzzjTfeMEtLS82zzjrLbG5uNmtra+M/m6Zp1tXVmVdffbX5wx/+0Gxqakpo/M2bN5vXXHNNhx7D888/b95xxx2maZrmrl27zHnz5iX8HO0xefJkc8mSJQmN/9e//tWcPXu2aZqmuWjRInPWrFkJjX/fffeZjz76qGmaprl06VLz1ltvPaj4pmmaS5YsMc855xxz2LBh8dfKE088YT788MOmaZrmK6+8Yt59990H/Ttuax8vvviied5555knn3zyt2InIv5DDz0Uf90UFhaa5557bkLjz5s3z5wzZ45pmqb5/PPPf+scHWp800xMO24rfnvt+FDjJ6oNf9f52WNfbTgR+0hUO24rfnvtuKvp6GtbZ869vfbQmXNvrx10htxN8+Cv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RxMWv7y8nKlTpxIKhYhEIkyZMqXVm89EnZ+2lh9q/Pba8aHGT2Qbbus8fFcbTsQ+EtmO9xW/vXbc1XT0ta0z595ee+jMubfXDjpL7nsc6LWss+be3jWsM+e+t++zrXb0dasz557MdtpV7JnFeP369Zimyb333vut9zfy3bZt28aNN97Is88+S1FRETNmzGjz9SvfdjB/B2TfgsEgt9xyC+Xl5YTDYa6++moKCgr0mjwEEydO5M4778RisXTr85iUAqGIiIiIiIiIiIh0Dkm7B6GIiIiIiIiIiIgknwqEIiIiIiIiIiIi3ZgKhCIiIiIiIiIiIt2YCoQiIiIiIiIiIiLdmAqEIiIiIiIiIiIi3ZgKhCIiIiIiIiLyLY899hiXX345V1xxBVdeeSWrV68GYOLEiRQWFn5veUQiEa688kouueQSampqvnPbbdu2cdFFFwEwduxYmpubW62fOHEiF1xwARMnTuSyyy7j7LPP5t133/3OmIsWLaKlpYU1a9bwyCOPHNrBtOHPf/4zq1evZteuXUyYMIHLLruMkpISAP7+97/zz3/+M77tu+++y3PPPdcheUj3ZUt2AiIiIiIiIiLSuWzcuJHFixfzzDPPYBgGa9asYerUqbz88svfey5lZWVUVVXxwgsvJCTe7NmzKSgoAGDTpk1cf/31jB49us3t586dy7nnnsvgwYMZPHhwQnLY286dO1m/fj2/+MUvmDdvHldddRWmafLqq69yySWXsHjxYv7whz/Etx89ejRXXXUV48ePx+/3Jzwf6Z5UIBQRERERpkyZwtlnn82YMWMoLCxk9uzZZGZmUlxcTDQa5be//S0jRozgtdde4+mnn44/76GHHmLDhg088MAD2O12LrroIs4999wkHomIiCRCeno6O3bs4LnnnmPUqFEMHjy4Va+1P/7xj5SXl9PY2Mj//M//kJOTw+23386uXbuoqqpi1KhR/Pa3v2XatGlUV1dTXV3N3Llz+d///V8+/vhjTNPk8ssv5yc/+Umr/b788svMnz8fh8NBv379uOuuu5gxYwabN2/m9ttv56677opvu3z58niPvqamJmbPno3dbj+g49yxYweBQKDNeCtWrKCsrIwbbriBn//85yxcuJAHH3yQcePGMXz4cIqKisjIyGDOnDm0tLRw8803U1paSq9evfj44495//33efrpp3nppZewWCwMHz6cqVOntsrhmWeeYfz48QB4PB6CwSCmaeJ2u5k3bx6TJk3CMIxWzxk9ejQvvvgikyZNOqDjFWmLhhiLiIiICBdeeCEvvvgiAM899xzDhg0jLS2Np59+mj/96U/xN2SbN2/mscceY8GCBfTv35/3338fgObmZv7v//5PxUERkS4iPT2dRx99lE8++YSLL76YM844g7fffju+fvTo0Tz55JOMGjWK1157jZ07dzJ06FAef/xxnnnmGZ555pn4tj/84Q9ZuHAhn332Gdu2bWPhwoU8+eST/PnPf6a2tja+XVVVFXPmzGH+/Pk888wz+P1+Fi1axB133MGAAQNaFQcBNmzYwP3338+TTz7J2LFjee211/br2KZOncqECRMYNWoUzz77LLNmzWoz3oUXXkhWVhYPPvhgqxhbt27lN7/5DYsWLaKyspJVq1axaNEi+vTpw8KFC/n1r39NRUUFAC+88AK33XYbixYtIjc3l3A43CrW8uXLOeKIIwA466yz+OCDD1i+fDknn3wyxcXFmKbJ7bffzt/+9rf4c4444giWL1++X8crsj/Ug1BEREREGDFiBPfccw8VFRUsXbqUYcOG8cknn/DFF18AEA6HqaqqIiMjg6lTp+L1etm0aRNDhw4FoH///slMX0REEqy4uBifzxcvnq1atYrJkyczYsQIAIYMGQJAZmYm5eXlpKamsmrVKj788EN8Ph+hUCgea881Yv369Xz55ZdMnDgRiF1b9u7Bt3XrVgYMGIDP5wPgBz/4Ae+//z5jxozZZ449evTgnnvuwePxUFJSwvDhw/fr2PYMMV64cCGvvPIKvXr1OuB4aWlp8ef16tWL5uZmCgsLGTVqFAAFBQWkp6cDMGvWLJ544gkeeOABhg4dimmarWJVVVWRmZkJgNfrjZ/zu+++m2uvvZa77rqLuXPncv3113PmmWfi8XjIysqiurp6v45XZH+oB6GIiIiIYBgGZ599Nvfccw8jR46koKCAM888kwULFvCXv/yFM844A5vNxsMPP8yDDz7IzJkzcTqd8Tc5Fov+rRQR6UrWrVvHnXfeGZ/ko3///vj9fqxW6z63f+GFF/D7/fz+97/niiuuoKmpKX6N2DM8Nj8/nxEjRrBgwQLmz5/PT37yE/r06ROP0adPHwoLCwkGg0CsZ913fQA1ffp07r33Xu677z6ys7O/VXhrz4QJE+jVq1e8d2Bb8QzDIBqNtnruN4f8AgwaNIhPP/0UgC1btlBVVQXAs88+y+9+9zueeuop1qxZE99mj/T09FY9KSFWTHU6neTl5dHc3IxhGEQikXjhtba2Nl6AFEkE9SAUEREREQB+9rOfMWbMGP7+97+Tm5vL9OnT+c///E/q6+u59NJL8fl8DB8+nPPOOw+Px0MgEKC0tLTVmzsREekaxo0bR2FhIRdeeCEejwfTNLn55pvbnBTjpJNO4sYbb2TlypW43W769u1LaWlpq23Gjh3L8uXLufTSSwkGg5x22mnx3oIQK5Rdd911TJo0CYvFQl5eHv/1X/9FWVnZPvd5zjnncNFFFxEIBMjMzPzW/vbHbbfdxn/8x39wzjnntBnvhBNOYPLkyfzqV7/6zlgXXHAB06ZN47LLLiMnJwen0wnEhgNfcMEFpKWl0aNHD4477rhWzzvxxBP5/PPPycnJiS+bO3cut99+OwDnnnsuF198MUOGDCE1NRWAzz//nJNOOumAj1ekLYZ5oCV2EREREemSSkpKuPnmm5k/f36yUxERETnsfPLJJwSDQX70ox+xefNmrrrqKt566612n7d9+3Zmz57Nww8/vN/7uvLKK3nooYdaFVhFDoV6EIqIiIgIr7/+Oo888gj33HNPslMRERE5LOXm5nLjjTfyyCOPEA6H4z0A29O7d2+OOOIIVq1axTHHHNPu9u+88w7jx49XcVASSj0IRUREREREREREujHdTVpERERERERERKQbU4FQRERERERERESkG1OBUEREREREREREpBtTgVBERERERERERKQbU4FQRERERERERESkG/v/hxUhaEjIrbYAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 1296x288 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(ncols=3, figsize=(18, 4))\n",
    "yelp_reviews.year.value_counts().sort_index().plot.bar(title='Reviews per Year', ax=axes[0], rot=0);\n",
    "sns.lineplot(x='year', y='stars', data=yelp_reviews, ax=axes[1])\n",
    "axes[1].set_title('Stars per year')\n",
    "\n",
    "stars_dist = yelp_reviews.stars.value_counts(normalize=True).sort_index().mul(100)\n",
    "stars_dist.index = stars_dist.index.astype(int)\n",
    "stars_dist.plot.barh(title='# Stars Breakdown', ax=axes[2])\n",
    "axes[2].set_xlabel('Share of all Ratings (%)')\n",
    "axes[2].set_ylabel('Number of Stars');\n",
    "\n",
    "sns.despine()\n",
    "fig.tight_layout();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Years of Membership Breakdown"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:32:54.923579Z",
     "start_time": "2020-06-20T22:32:54.668404Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3deVRTZ/4/8HfYQiEs4tJOS1EQcascUdwVRW1xt6IixMZaPW1xXAa0FkRAEPeFr1aHio792YKAdrS21s5Ux1FRqA7HjmtFRwYV0LqBQqKyJM/vDw8ZqdIoJvFi3q9zeg65ufk8H1Lg7XNz73NlQggBIiIiibF60Q0QERE9CQOKiIgkiQFFRESSxIAiIiJJYkAREZEkMaCIiEiSGFDU6CUmJiIkJARarVa/TavVIjQ0FP/3f//3Ajv7n507d2LAgAGYOnVqne3FxcVo27Yt3nvvvcdeEx0djbZt26K0tNQoPaxbtw4LFy40Sq3fKi4uhp+f3xOfy8zMxMaNG00yLr3cGFDU6EVHR+P+/ftITU3Vb0tNTYW1tTVmzZr1Ajv7n127diEyMhKbN29+7Dm5XI7CwkKUlJTot927dw8///yzOVs0mbCwMHz00Ucvug1qhGxedANEz0sul2PVqlUICwtDYGAghBDIyMjAjh07YG1tja+//hqZmZnQ6XRwdXVFXFwcWrdujcLCQixcuBAajQY3b95Eu3btsGbNGsjlcrz11lsYNGgQ8vPzsWrVKhw4cAD79u2Dra0tmjRpgqVLl6JFixZ1+qioqEBiYiLy8/Mhk8nQr18/zJ49GytWrMDp06dRXFyMsrIyTJ48uc7rrK2tMXToUOzevRvh4eEAgL1792LQoEH44osv9Pv985//xOeff47q6mrY29sjKioKfn5+WLduHa5cuYLr16/j5s2b6NixI3r06IFdu3ahuLgYc+fOxYgRIwAABQUFmDhxIu7evYv27dtjwYIFUCgUuH79OhYuXIhr166huroaw4cPR3h4OIqLizFx4kS0bt0aJSUl2LJlCzZs2ICff/4Ztra2cHd3x9KlSwE8nLXGx8fj9OnTqKiowNy5cxEUFIR169ahrKwM8fHxGDhwIIYPH46cnBxUVFTggw8+gFKpNOFPBzVqgugl8dVXX4kxY8aI0aNHi4MHDwohhDh27JhQKpXi3r17QgghDh8+LIYMGSKEEGLZsmVi165dQgghqqqqxIgRI8Tf//53IYQQPj4+4ptvvhFCCHH16lXRpUsXUVlZKYQQYvPmzWLfvn2Pjf/pp5+KpKQkodPpRGVlpZgyZYpITU0VQgjx3nvvib/97W+PvaaoqEh07txZnD59Wt+XEEK8//774vz588LHx0fcvn1bFBYWihEjRojS0lIhhBAXLlwQffr0ERqNRnz22WciMDBQlJeXi/v374tu3bqJpUuXCiGE2Ldvn3jnnXeEEEJ89tlnYsCAAeL27dtCp9OJOXPmiBUrVgghhFCpVGL//v1CCCEePHggVCqV2LNnjygqKhI+Pj4iLy9PCCFEXl6eGDJkiNDpdEIIIVasWCGOHz+u36/2/du7d68YNGiQftzExEQhhBCBgYEiLi5O6HQ6ce3aNdGjRw+Rn5//lP+HydJwBkUvDZVKhR9//BGtW7dG//79AQAHDx7E5cuXERoaqt+vvLwcd+7cwdy5c5GTk4NNmzbh0qVLuHHjBu7du6ffz9/fHwDw6quvol27dhgzZgwCAgIQEBCAXr16PTZ+dnY2MjMzIZPJYGdnh9DQUHz55ZdPdXjrrbfegrW1Nc6cOYOmTZtCo9HAx8dH/3xOTg5u3LhRZ/Ylk8lw5coVAEDv3r3h5OQEAGjRogX69esHAPDw8MCdO3f0r3n77bfh5uYGABg7dixWrFiBe/fuIS8vD3fv3sXatWsBPDzEmJ+fD19fX9jY2KBz584AAB8fH1hbW2P8+PHo27cvgoKC4Ovri+LiYtja2iIoKAgA0K5dO9y+ffuJ36tSqYRMJsNrr72Gfv36IScnB23btjX4HpHlYUDRS8Xd3R0eHh76xzqdDqNHj8bcuXP1j2/cuAEXFxdERkZCq9Vi6NChGDBgAK5duwbxyNKUDg4OAAArKyukp6fj9OnT+Omnn7BkyRL069cPn376aZ2xdTodZDJZncc1NTVP3fuoUaPw3Xffwc3NDaNHj36sdq9evbBmzRr9tmvXrqFFixbYt28f7Ozs6uxvY/PkX21ra+s6NW1sbKDT6SCEQFZWFl555RUAQGlpKeRyOcrKymBnZ6ev5+zsjG+//RY///wzjh49ioiICEydOhX9+/eHra2tvvaj78NvPdqbTqeDlRU/Cqcn408GvdT69u2LPXv24MaNGwAenlH2/vvvAwCOHDmC6dOnY9iwYQCAkydP1jkTsFZ+fj5GjBiB1q1b4+OPP8bkyZNx+vTpJ46Vnp4OIQSqqqqwfft29O7d+6l7HT16NP7+97/jhx9+0H9mVKtXr17IyclBQUEBAODQoUMYNWoUHjx48NT1gYefY929exdarRbbt29HQEAAFAoFOnfujP/3//4fgIczzLCwMOzfv/+x1x84cACTJ0+Gn58fZs6ciXfffRdnzpx5ph527doFALh69SpycnIQEBDwTK8ny8EZFL3U+vbtiw8//BBTpkyBTCaDQqHA+vXrIZPJEBkZienTp8PBwQEKhQLdunXTHzJ7VLt27TB06FCMHTsWDg4OsLe3R2xs7GP7xcbGYtGiRRg5ciSqq6vRr18//UkPT+PVV19F69at4eTkBFdX1zrPeXt7Y+HChZg9ezaEELCxscHnn38OR0fHZ3o/akO2vLwcXbt21R9+XLVqFZKSkjBy5EhUVVVhxIgRGDVqFIqLi+u8PiAgANnZ2RgxYgQcHBzg4uKCpKSkZ+qhuLgYwcHBePDgAWJjY+Hl5fVMryfLIROCt9sgIvMYOHAg1q5di06dOr3oVqgR4CE+IiKSJM6giIhIkjiDIiIiSWJAERGRJL00AfXbRTiJiKhxe2kCqqys7EW3QERERvTSBBQREb1cGFBERCRJDCgiIpIkBhQREUkSA4qIiCSJAUVERJJksoA6efIkVCoVAODy5csICwuDUqnEggULoNPpAADbt29HcHAwQkJCcODAAQDAgwcPMHPmTCiVSnz44YcoLS01VYtERCRhJgmoTZs2ITY2FpWVlQCApUuXIiIiAhkZGRBCYP/+/bh58ybS0tKQlZWFzZs3Izk5GVVVVcjMzISPjw8yMjLw7rvvIiUlxRQtEhGRxJkkoDw8PLBu3Tr947Nnz6J79+4AHt5PJjc3F6dOnYKfnx/s7Ozg5OQEDw8P5Ofn4/jx4/rbVQcEBOCnn34yRYtERCRxJgmooKCgOrd1FkLobwHt6OiIiooKqNVqODk56fdxdHSEWq2us712X6IH1Y/f6daY+xOR9JjljrpWVv/LQY1GA2dnZygUCmg0mjrbnZyc6myv3ZfI3tYaraL3PPX+l5YNN2E3RGQOZjmLr0OHDjh27BgAIDs7G/7+/vD19cXx48dRWVmJiooKFBQUwMfHB126dMGhQ4f0+3bt2tUcLRIRkcSYZQYVFRWFuLg4JCcnw8vLC0FBQbC2toZKpYJSqYQQApGRkZDL5QgLC0NUVBTCwsJga2uL1atXm6NFIiKSmJfmjrrBwcHYuXPni26DTIiH+Op6UK2Fva21yfYnetHMMoMikrLG+oeen8vRy44BRRaPf+iJpIlLHRGZEE+PJ2o4zqCITIizM6KG4wyKiIgkiQFFRESSxIAiIiJJYkAREZEkMaDIaHjGGhEZE8/iI6PhGWtEZEycQRERkSQxoIiISJIYUEREJEkMKCIikiQGFBERSRIDioiIJIkBRUREksSAIiIiSWJAERGRJDGgiIhIkhhQREQkSQwoIiKSJAYUERFJEgOKiIgkiQFFRESSxIAiIiJJYkAREZEkMaCIiEiSGFBERCRJDCgiIpIkBhQREUkSA4qIiCSJAUVERJLEgCIiIkmyMddA1dXViI6ORklJCaysrJCUlAQbGxtER0dDJpOhTZs2WLBgAaysrLB9+3ZkZWXBxsYG06ZNQ2BgoLnaJCIiiTBbQB06dAg1NTXIyspCTk4O1qxZg+rqakRERKBHjx6Ij4/H/v370blzZ6SlpWHHjh2orKyEUqlEnz59YGdnZ65WiYhIAp7qEJ9arUZJSQnu37/f4IE8PT2h1Wqh0+mgVqthY2ODs2fPonv37gCAgIAA5Obm4tSpU/Dz84OdnR2cnJzg4eGB/Pz8Bo9LRESN0+/OoHbt2oWMjAzcuXMHbm5uqKiogLOzM5RKJUaOHPlMAzk4OKCkpARDhw5FWVkZNmzYgLy8PMhkMgCAo6MjKioqoFar4eTkpH+do6Mj1Gp1A741IiJqzOoNqOjoaHTp0gV/+ctf4OzsrN9eUVGB3bt3Y+7cuVi5cuVTD7Rlyxb07dsXc+bMwbVr1/D++++jurpa/7xGo4GzszMUCgU0Gk2d7Y8GFhERWYZ6AyoxMRFyufyx7U5OTlAqlRg7duwzDeTs7AxbW1sAgIuLC2pqatChQwccO3YMPXr0QHZ2Nnr27AlfX1+sWbMGlZWVqKqqQkFBAXx8fJ7x2yIiosau3oCSy+U4d+4cfvrpJ/2hva5du8LX11f//LOYPHkyYmJioFQqUV1djcjISLz11luIi4tDcnIyvLy8EBQUBGtra6hUKiiVSgghEBkZ+cxjERFR41dvQK1fvx6nTp1C37594e7uDo1Gg/Xr16NDhw6IiIh45oEcHR2xdu3ax7anp6c/ti0kJAQhISHPPAYREb086g2o3NxcZGRk1NmmUqkQEhLSoIAiIiJ6FvWeZl5TU4Pi4uI624qLi2FlxcUniIjI9OqdQcXExGDGjBmorq6GQqGAWq2GnZ0dEhMTzdkfERFZqHoDqnPnzti1axfUajU0Gg0cHR2hUCjM2RsREVmwegOqrKwMKSkpOHr0KCoqKuDk5AR/f3/MmDEDTZs2NWePRERkger9QCk6Ohp+fn7IzMzEgQMHkJmZCX9/f8yZM8ec/RERkYWqN6DUajWGDRsGhUIBmUwGhUKB4cOHo6qqypz9ERGRhar3EF/Tpk2xfv16BAQE6JcfOnToEJo3b27O/oiIyELVG1ArV65EZmYmNm3aBI1GA4VCAT8/Pyxfvtyc/RERkYX63aWOJk6ciK5du0KtVsPZ2Rlt2rThfZmIiMgs6g2ogwcPYvXq1WjVqhUcHByg0Wjw3//+F7Nnz8bgwYPN2SMREVmgegNqw4YNyMzMrHPtU0VFBSZPnsyAIiIik6v3LL7q6mrY29vX2SaXy/U3GKTG6UG11qT7ExEZS70zqAkTJmDMmDHo2rUrnJycoFarcfz4cahUKnP2R0Zmb2uNVtF7nnr/S8uGm7AbIqL61RtQISEhGDhwIE6dOgW1Wg2FQoHp06ejWbNm5uyPiIgsVL0BpVKp8Oqrr2L+/Plo0qSJOXsiIiKqP6BmzpyJZs2aMZyIiOiFqPckiZycHLi5uT3xudLSUqxevdpkTRHRi8WTaUgK6p1BBQcHIyYmBkIItG3bFs2aNUN5eTlOnjwJKysrzJ0715x9EpEZ8WQakoJ6A6ply5ZISUlBYWEh8vLyUFZWhubNm2P+/Pnw8PAwZ49ERGSB6g2oWp6envD09DRHL0RERHr1fgZFRET0IjGgiIhIkhhQREQkSQwoIiKSJAYUERFJksGAysvLQ3Z2Ng4dOoTBgwdj9+7d5uiLiIgsnMGAWrlyJVq1aoWvvvoKmZmZyMrKMkdfRERk4QwGlFwuR9OmTWFjY4PmzZujqqrKHH0REZGFMxhQCoUCH3zwAYYOHYqtW7fiD3/4gzn6IiIiC2dwJYlPPvkEQgh4e3vjwoULGD9+vDn6IiIiC2dwBhUbGwtvb28AgI+PD+zs7EzeFBERkcEZlIODA5YsWQJPT09YWT3MswkTJpi8MSIismwGA8rPzw8AcPv2bZM3Q0REVMtgQM2YMQO5ubkoLi6Gr68vVzYnIiKzMBhQycnJ+PXXX1FQUABbW1ts3LgRycnJDRosNTUV//znP1FdXY2wsDB0794d0dHRkMlkaNOmDRYsWAArKyts374dWVlZsLGxwbRp0xAYGNig8YiIqPEyeJLE8ePHsWLFCjg4OGDMmDEoLi5u0EDHjh3Dv//9b2RmZiItLQ2//vorli5dioiICGRkZEAIgf379+PmzZtIS0tDVlYWNm/ejOTkZF57RURkgQwGlFarRWVlJWQyGbRarf5EiWd15MgR+Pj4YPr06QgPD8eAAQNw9uxZdO/eHQAQEBCA3NxcnDp1Cn5+frCzs4OTkxM8PDyQn5/foDGJiKjxMniI7/3330dwcDBKS0sxfvx4TJ48uUEDlZWV4erVq9iwYQOKi4sxbdo0CCEgk8kAAI6OjqioqIBarYaTk5P+dY6OjlCr1Q0ak4iIGi+DATV06FD07t0bV65cgbu7O5o0adKggVxdXeHl5QU7Ozt4eXlBLpfj119/1T+v0Wjg7OwMhUIBjUZTZ/ujgUVERJbB4PG606dP44MPPsD06dMxbdo0nD9/vkEDde3aFYcPH4YQAtevX8f9+/fRq1cvHDt2DACQnZ0Nf39/+Pr64vjx46isrERFRQUKCgrg4+PToDGJiKjxMjiDWrx4MVasWAFvb2+cP38eiYmJyMjIeOaBAgMDkZeXh3HjxkEIgfj4eLi7uyMuLg7Jycnw8vJCUFAQrK2toVKpoFQqIYRAZGQk5HJ5g745IiJqvAwGlFwu1y911LZtW9ja2jZ4sE8//fSxbenp6Y9tCwkJQUhISIPHISKixq/egNq2bdvDHWxskJCQgG7duuHUqVNQKBRma46IiCxXvQF18+ZNAP9b6qiwsBBOTk5o3769eTojIiKLVm9AzZgxA8DD66D+85//8GJZIiIyK4OfQX300UeoqqqCs7MzAEAmk2H9+vUmb4yIiCybwYCqrKx84okMREREpmQwoPz9/XH48GG0bt1av+311183aVNEREQGA+r27dtYsmRJnUN8WVlZJm+MiIgsm8GAKiwsxN/+9jdz9EJERKRncKkjHx8fnDhxAlVVVfr/iIiITM3gDCovLw8HDx7UP5bJZNi/f78peyIiIjIcULt37wYA3LlzBy4uLvrbYxAREZnSU82gEhMTodVqMWTIELz++usYP368OXojIiILZvAzqDVr1iA9PR3NmjVDeHg4MjMzzdEXERFZOIMBZWVlBVdXV8hkMsjlcjg6OpqjLyIisnAGA8rDwwOrV6/GnTt3sHHjRl6kS0REZmEwoBITE/H666+ja9eucHBwQFJSkjn6IiIiC1fvSRJ5eXn6r729vfU3LTx58iS6detm+s6IiMii1RtQKpUKHh4e6NSpEwBACAHg4XVQDCgiIjK1egNqx44d+P7773H27Fn07NkTI0eOxJtvvmnO3oiIyILVG1AdO3ZEx44dIYTA0aNH8fnnn+PWrVsYOHAgQkNDzdkjERFZIIMnSchkMvj5+aF3797Q6XT4+uuvzdEXERFZuHpnUNXV1cjOzsb333+PS5cuYeDAgZg/fz48PT3N2R8REVmoegOqd+/eaNGiBYYPH47g4GDIZDKUlJSgpKQEffv2NWePRERkgeoNqEGDBkEmk6GoqAhFRUV1nmNAERGRqdUbUMuWLTNnH0RERHUYPEmCiMiYHlRrTbo/vTzqnUFVVFTAycnJnL0QkQWwt7VGq+g9T73/pWXDTdgNSVm9M6jw8HAAwIIFC8zWDBERUa16Z1D29vYYO3YsLl++jPPnzwN4uNyRTCZDVlaW2RokIiLLVG9Abdq0CTdu3EB8fDwSEhL0a/GR6T2o1sLe1tpk+xMRNQb1BpSVlRVee+01pKSkYNu2bbh48SJatWqFsLAwc/ZnkXiMnojoKc7ii4+Px5UrV9CnTx+UlJQgNjbWHH0REZGFq3cGVevy5cvYunUrAGDw4MFcKJaIiMzC4AyqsrIS9+/fBwA8ePAAWi2vSSAiItMzOIOaNGkSRo8ejTZt2uDixYuYNWuWOfoiIiILZzCgRo0ahYCAABQVFcHd3R1NmjR5rgFv376N4OBgfPHFF7CxsUF0dDRkMhnatGmDBQsWwMrKCtu3b0dWVhZsbGwwbdo0BAYGPteYRETU+DzVUkeurq7o1KnTc4dTdXU14uPjYW9vDwBYunQpIiIikJGRASEE9u/fj5s3byItLQ1ZWVnYvHkzkpOTUVVV9VzjEhFR42PWtfiWL1+O0NBQtGjRAgBw9uxZdO/eHQAQEBCA3NxcnDp1Cn5+frCzs4OTkxM8PDyQn59vzjaJiEgCDAbU5s2bjTLQzp074ebmhn79+um31a5MAQCOjo6oqKiAWq2uswago6Mj1Gq1UXogIqLGw2BAHTp0yChn7u3YsQO5ublQqVQ4d+4coqKiUFpaqn9eo9HA2dkZCoUCGo2mznYuWktEZHkMniRRVlaGfv36wd3dHTKZrMFr8dVeSwUAKpUKCQkJWLlyJY4dO4YePXogOzsbPXv2hK+vL9asWYPKykpUVVWhoKAAPj4+zzweERE1bgYDasOGDSYbPCoqCnFxcUhOToaXlxeCgoJgbW0NlUoFpVIJIQQiIyMhl8tN1gMREUmTwYCysbHBypUrUVZWhqCgILRt2xZvvPHGcw2alpam/zo9Pf2x50NCQhASEvJcYxARUeNm8DOouLg4jB07FlVVVfD398fixYvN0RcREVm4p1rqqFevXpDJZPDy8uLhNiIiMguDAWVnZ4fDhw9Dp9PhxIkTsLOzM0dfRERk4QwGVFJSEnbu3ImysjJ88cUXSEhIMENbRERk6QyeJPHaa6/h448/xqVLl9CmTRu8+eab5uiLiIgsnMGASklJweHDh9GpUyds2bIFQ4YMweTJk83QGhERWTKDAZWdnY2MjAxYWVmhpqYGSqWSAUVERCZn8DMoNzc3/Q0Lq6ur4ebmZvKmiIiI6p1BTZgwATKZDLdv39ZfoFtQUABXV1dz9kdERBaq3oBKTk42Zx9ERER11BtQtcsZnTp1Cnv27EFlZaX+OZ5qTkREpmbwJImoqCh8+OGHcHZ2Nkc/REREAJ4ioFq2bIng4GBz9EJERKRnMKCCgoIQGRmJ1q1b67fNmDHDpE0REREZDKiMjAy8/fbbPMRHRERmZTCgXFxc8NFHH5mjFyIiIj2DAdWkSRPEx8ejQ4cOkMlkAB5eI0VERGRKT3WSBADcunXL5M0QERHVMhhQPIOPiIheBIMBFRkZCZlMBp1Oh+LiYrRs2RKZmZnm6I2IiCyYwYDatm2b/uvy8nLEx8ebtKHG4kG1Fva21ibbn4jI0hkMqEc5OTnhypUrpuqlUbG3tUar6D1Pvf+lZcNN2A0R0cvHYEDVrmouhEBpaSl69epljr6IiMjCGQyoR1c1l8vlaNasmUkbIiIiAn4noHbt2lXvi959912TNENERFSr3oAqKCio81gIgZ07d8Le3p4BRUREJldvQM2ZM0f/9eXLlxEdHY0BAwYgJibGLI0RET0rnl37cjH4GdTWrVvx5ZdfYt68eQgMDDRHT0REDcKza18u9QbU9evXMW/ePLi4uODrr7+Gi4uLOfsiIiILV29AjRgxAra2tujZsycWLlxY57nVq1ebvDEiIrJs9QbUn//8Z3P2QUREVEe9AdW9e3dz9kFERFSH1YtugIiI6EkYUEREJEnPtFjs86iurkZMTAxKSkpQVVWFadOmwdvbG9HR0ZDJZGjTpg0WLFgAKysrbN++HVlZWbCxscG0adN4ejsRkQUyW0B99913cHV1xcqVK1FWVoYxY8agXbt2iIiIQI8ePRAfH4/9+/ejc+fOSEtLw44dO1BZWQmlUok+ffrAzs7OXK0SEZEEmC2ghgwZgqCgIP1ja2trnD17Vn8yRkBAAHJycmBlZQU/Pz/Y2dnBzs4OHh4eyM/Ph6+vr7laJSIiCTDbZ1COjo5QKBRQq9WYNWsWIiIiIISATCbTP19RUQG1Wg0nJ6c6r1Or1eZqk4iIJMKsJ0lcu3YNkyZNwujRozFy5EhYWf1veI1GA2dnZygUCmg0mjrbHw0sIiKyDGYLqFu3bmHKlCmYO3cuxo0bBwDo0KEDjh07BgDIzs6Gv78/fH19cfz4cVRWVqKiogIFBQXw8fExV5tERCQRZvsMasOGDSgvL0dKSgpSUlIAAPPnz8eiRYuQnJwMLy8vBAUFwdraGiqVCkqlEkIIREZGQi6Xm6tNIiKSCLMFVGxsLGJjYx/bnp6e/ti2kJAQhISEmKMtIiKSKF6oS0REksSAIiIiSWJAERGRJDGgiIhIkhhQREQkSQwoIiKSJAYUERFJ0ksdUA+qtSbdn4iITMdsF+q+CPa21mgVveep97+0bLgJuyEiomfxUs+giIio8WJAERE9BX5kYH4v9SE+IiJj4UcG5scZFBERSRIDioiIJIkBRUREksSAIiIiSWJAERGRJDGgiIhIkhhQREQkSQwoIiKSJAYUERFJEgOKiIgkiQFFRESSxIAiIiJJYkAREZEkMaCIiEiSGFBERCRJDCgiIpIkBhQR0QvGu/U+Ge+oS0T0gvFuvU/GGRQREUkSA4qIiCSJAUVERJLEgCIiIkliQBERkSRJ8iw+nU6HhIQEnD9/HnZ2dli0aBFatmz5otsiIiIzkuQM6h//+Aeqqqqwbds2zJkzB8uWLXvRLRERNUqN+RorSc6gjh8/jn79+gEAOnfujDNnzrzgjoiIGqfGfI2VTAghXnQTvzV//ny888476N+/PwBgwIAB+Mc//gEbm/rztEePHnjjjTfM1SIRERlJkyZNsHnz5se2S3IGpVAooNFo9I91Ot3vhhMAHDt2zNRtERGRGUnyM6guXbogOzsbAHDixAn4+Pi84I6IiMjcJHmIr/YsvgsXLkAIgSVLlqB169Yvui0iIjIjSQYUERGRJA/xERERMaCIiEiSGFBERCRJFhVQOp0O8fHxmDBhAlQqFS5fvmz0MU6ePAmVSmXUmtXV1Zg7dy6USiXGjRuH/fv3G622VqvFvHnzEBoaiokTJ+LKlStGqw0At2/fRv/+/VFQUGDUuk0nbSUAAAt+SURBVADw7rvvQqVSQaVSYd68eUatnZqaigkTJiA4OBhff/210eru3LlT33NISAg6deqE8vJyo9Surq7GnDlzEBoaCqVSadT3vKqqCnPmzEFISAimTJmCS5cuGaXuo78vly9fRlhYGJRKJRYsWACdTme02gCwb98+zJkz57lqPqn2uXPnoFQqoVKpMHXqVNy6dctotS9evIiwsDCEhoYiISEBWu3zrfLwpL9Pu3fvxoQJE56r7m9rnz17Fv369dP/rP/www8NKyosyI8//iiioqKEEEL8+9//FuHh4Uatv3HjRjFixAgxfvx4o9b961//KhYtWiSEEKK0tFT079/faLX37dsnoqOjhRBCHD161KjvSVVVlfjjH/8o3nnnHXHx4kWj1RVCiAcPHojRo0cbtWato0ePio8//lhotVqhVqvFZ599ZpJxEhISRFZWltHq7du3T8yaNUsIIcSRI0fEjBkzjFY7LS1NxMbGCiGEKCgoEFOmTHnumr/9ffn444/F0aNHhRBCxMXFib179xqtdlJSkggKChIRERFG73vixInil19+EUIIkZmZKZYsWWK02tOmTRP/+te/hBBCREVFGfU9EUKIX375RUyaNOm5/2b9tvb27dvF5s2bn6umEEJY1AzK1EsoeXh4YN26dUatCQBDhgzBn/70J/1ja2tro9UePHgwkpKSAABXr15Fs2bNjFZ7+fLlCA0NRYsWLYxWs1Z+fj7u37+PKVOmYNKkSThx4oTRah85cgQ+Pj6YPn06wsPDMWDAAKPVrnX69GlcvHjRKP9yreXp6QmtVgudTge1Wm3w4vZncfHiRQQEBAAAvLy8jDI7++3vy9mzZ9G9e3cAQEBAAHJzc41Wu0uXLkhISGhwvd+rnZycjPbt2wN4eERCLpcbrfa6devQrVs3VFVV4ebNm2jatKnRapeVlWHVqlWIiYlpcM36ap85cwYHDx7ExIkTERMTA7Va3aC6FhVQarUaCoVC/9ja2ho1NTVGqx8UFGTUPwq1HB0doVAooFarMWvWLERERBi1vo2NDaKiopCUlISgoCCj1Ny5cyfc3Nz0/yAwNnt7e0ydOhWbN29GYmIiPvnkE6P9vywrK8OZM2ewdu1afW1h5KsxUlNTMX36dKPWdHBwQElJCYYOHYq4uDijHmpu3749Dhw4ACEETpw4gevXrz/34abf/r4IISCTyQA8/JmvqKgwWu1hw4bpaz+v39au/QfYzz//jPT0dEyePNlota2trVFSUoIRI0agrKwMnp6eRqmt1Woxf/58xMTEwNHRscE16+vb19cXn376KbZu3Yo333wTf/7znxtU16ICqiFLKEnFtWvXMGnSJIwePRojR440ev3ly5fjxx9/RFxcHO7du/fc9Xbs2IHc3FyoVCqcO3cOUVFRuHnzphE6fcjT0xOjRo2CTCaDp6cnXF1djVbf1dUVffv2hZ2dHby8vCCXy1FaWmqU2gBQXl6O//73v+jZs6fRagLAli1b0LdvX/z444/49ttvER0djcrKSqPUHjt2LBQKBSZNmoQDBw6gY8eORp3JA4CV1f/+HGk0Gjg7Oxu1vin98MMPWLBgATZu3Ag3Nzej1n7jjTewd+9ehIWFGe3ODmfPnsXly5eRkJCA2bNn4+LFi1i8eLFRagPA22+/jbfeekv/9S+//NKgOhYVUI11CaVbt25hypQpmDt3LsaNG2fU2rt27UJqaioA4JVXXoFMJjPKH56tW7ciPT0daWlpaN++PZYvX47mzZs/d91af/3rX/W/rNevX4darTZa/a5du+Lw4cMQQuD69eu4f/8+XF1djVIbAPLy8tC7d2+j1avl7OwMJycnAICLiwtqamqee5ZT6/Tp0+jatSvS0tIwePBgvPnmm0ap+6gOHTro19TMzs6Gv7+/0ccwhW+//Vb/s27s9yU8PFx/Qoqjo2OdEH8evr6+2LNnD9LS0pCcnAxvb2/Mnz/fKLUBYOrUqTh16hQA4KeffkLHjh0bVKdxTB+M5O2330ZOTg5CQ0P1Syg1Bhs2bEB5eTlSUlKQkpICANi0aRPs7e2fu/Y777yDefPmYeLEiaipqUFMTMxzHUM3l3HjxmHevHkICwuDTCbDkiVLjDYbDgwMRF5eHsaNGwchBOLj4406WygsLIS7u7vR6tWaPHkyYmJioFQqUV1djcjISDg4OBildsuWLbF27Vp88cUXcHJyMuq/tmtFRUUhLi4OycnJ8PLyMtrhZlPSarVYvHgx/vCHP2DmzJkAgG7dumHWrFlGqf/RRx8hOjoatra2eOWVV7Bo0SKj1DW1hIQEJCUlwdbWFs2aNdN/zv2suNQRERFJkkUd4iMiosaDAUVERJLEgCIiIkliQBERkSQxoIiISJIYUESPOHbsGPz9/XHt2jX9tlWrVmHnzp0NrllcXIyQkBBjtPcYrVaLqVOnIiwsDHfv3gXw8CLMwMBA/WMA+Oqrr4y+AgmRqTGgiH7D1tYW8+bNM/ryRqZw8+ZNlJWVITMzEy4uLgCAjh07Yty4cfprZq5cuYLMzEwsXLjwRbZK9Mws6kJdoqfRs2dP6HQ6bN26Fe+9955+e3FxMWbPno3t27cDAEJCQpCcnIxvvvkGly9fRllZGe7evQulUom9e/eisLAQy5cvR7NmzVBaWorw8HCUlpaif//+mD59Oq5du4a4uDhUVlZCLpcjKSkJWq0W06ZNg6urKwICAvDhhx/qx//uu+/w5Zdfws7ODq1atcLChQsRFxeHS5cuIT4+vk4AhYeHIzQ0FNnZ2diyZQsSEhLg7OyMtLQ0fP/995DJZBg2bBgmTZqECxcuYNmyZdDpdCgvL0dsbCy6dOmCwMBAeHl5wcvLC926dcOmTZtgY2ODN954AytWrDDaqgZE9Xru9dCJXiJHjx4VERERorS0VAwaNEgUFhaKlStXih07doiioqI6tyUYP368KCoqEp999pmYP3++EEKI1NRU/S0vam+TUlRUJHr16iXKy8tFTU2NmDBhgjh37pz405/+JA4ePCiEECI3N1fMnj1bFBUViR49eojKyso6fZWWlorBgweLiooKIYQQixcvFmlpaY/19KiCggLRu3dvsXLlSiGEEP/5z39EaGioqKmpEVqtVqhUKlFQUCD27Nkj8vPzhRBCfPfdd/rvpW3btqK0tFQIIcTMmTPF999/L4QQ4ptvvhF37959/jebyADOoIieoEmTJoiJiUF0dDS6dOnyxH3EI4cAO3ToAABwcnKCt7c3gIfr4dUu1tquXTv9OnmdOnVCYWEhLly4gNTUVPzlL3+BEAK2trYAAHd3d9jZ2dUZq6ioCN7e3vrV+Lt164YjR4787q1Aamc/Y8aMAQBcuHABV69e1a+2fffuXVy5cgUtWrRASkoK7O3todFo9GM0adIETZo0AQDMmzcPqampyMzMhJeXFwYPHvx0byTRc+AcnageAwcOhKenJ7755hsAgFwux+3bt6HValFeXo7i4mL9voZu5VBQUACNRoOamhqcOnUKbdq0gZeXFz755BOkpaUhMTFRv/bckw6dubu7o6CgQL/S/L/+9a9nvvWCl5cXvL298dVXXyEtLQ3BwcHw8fHB4sWLMWvWLCxfvhw+Pj764H20j23btmHmzJlIT08H8PDutESmxhkU0e+YP38+jh49CgBo3rw5+vTpg3HjxsHDwwMtW7Z86jouLi6IjIxEaWkphg0bBm9vb0RFRSEhIQGVlZV48ODB764m7ebmhpkzZ2LSpEmwsrKCh4cHPvnkk2e6xUi7du3Qq1cvhIWFoaqqCr6+vnj11VcxatQo/PGPf0TTpk3x2muvoays7LHX+vr64oMPPoCrqyscHR1NchNHot/iYrFERCRJPMRHRESSxIAiIiJJYkAREZEkMaCIiEiSGFBERCRJDCgiIpIkBhQREUnS/wf8ZnryGEbnxwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax = yelp_reviews.member_yrs.value_counts().div(1000).sort_index().plot.bar(title='Years of Membership',\n",
    "                                                                            rot=0)\n",
    "ax.set_xlabel('Number of Years')\n",
    "ax.set_ylabel(\"Number of Members  ('000)\")\n",
    "sns.despine()\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create train-test split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:33:25.049533Z",
     "start_time": "2020-06-20T22:33:23.276179Z"
    }
   },
   "outputs": [],
   "source": [
    "train = yelp_reviews[yelp_reviews.year < 2019].sample(frac=.25)\n",
    "test = yelp_reviews[yelp_reviews.year == 2019]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:33:25.053033Z",
     "start_time": "2020-06-20T22:33:25.050653Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Training Obs: 1,701,322 | # Test Obs: 1,215,836\n"
     ]
    }
   ],
   "source": [
    "print(f'# Training Obs: {len(train):,.0f} | # Test Obs: {len(test):,.0f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:34:12.665625Z",
     "start_time": "2020-06-20T22:34:03.973387Z"
    }
   },
   "outputs": [],
   "source": [
    "train.to_parquet(text_features_dir / 'train.parquet')\n",
    "test.to_parquet(text_features_dir / 'test.parquet')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:47.190096Z",
     "start_time": "2020-06-20T22:39:46.262021Z"
    }
   },
   "outputs": [],
   "source": [
    "del yelp_reviews"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Reload stored data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:47:45.765592Z",
     "start_time": "2020-06-20T23:47:41.008125Z"
    }
   },
   "outputs": [],
   "source": [
    "train = pd.read_parquet(text_features_dir / 'train.parquet')\n",
    "test = pd.read_parquet(text_features_dir / 'test.parquet')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create Yelp review document-term matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:37:23.986023Z",
     "start_time": "2020-06-20T22:34:18.938760Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<1701322x10000 sparse matrix of type '<class 'numpy.int64'>'\n",
       "\twith 75720724 stored elements in Compressed Sparse Row format>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vectorizer = CountVectorizer(stop_words='english', ngram_range=(1, 2), max_features=10000)\n",
    "train_dtm = vectorizer.fit_transform(train.text)\n",
    "train_dtm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:37:56.033921Z",
     "start_time": "2020-06-20T22:37:23.987293Z"
    }
   },
   "outputs": [],
   "source": [
    "sparse.save_npz(text_features_dir / 'train_dtm', train_dtm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:38.728292Z",
     "start_time": "2020-06-20T22:37:56.034993Z"
    }
   },
   "outputs": [],
   "source": [
    "test_dtm = vectorizer.transform(test.text)\n",
    "sparse.save_npz(text_features_dir / 'test_dtm', test_dtm)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reload stored data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:24:52.201913Z",
     "start_time": "2020-06-20T22:24:45.716756Z"
    }
   },
   "outputs": [],
   "source": [
    "train_dtm = sparse.load_npz(text_features_dir / 'train_dtm.npz')\n",
    "test_dtm = sparse.load_npz(text_features_dir / 'test_dtm.npz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Combine non-text features with the document-term matrix"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The dataset contains various numerical features. The vectorizers produce [scipy.sparse matrices](https://docs.scipy.org/doc/scipy/reference/sparse.html). To combine the vectorized text data with other features, we need to first convert these to sparse matrices as well; many sklearn objects and other libraries like lightgbm can handle these very memory-efficient data structures. Converting the sparse matrix to a dense numpy array risks memory overflow.\n",
    "\n",
    "Most variables are categorical so we use one-hot encoding since we have a fairly large dataset to accommodate the increase in features.\n",
    "\n",
    "We convert the encoded numerical features and combine them with the document-term matrix:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### One-hot-encoding "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:39.165235Z",
     "start_time": "2020-06-20T22:39:38.729447Z"
    }
   },
   "outputs": [],
   "source": [
    "df = pd.concat([train.drop(['text', 'stars'], axis=1).assign(source='train'),\n",
    "                test.drop(['text', 'stars'], axis=1).assign(source='test')])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:46.260771Z",
     "start_time": "2020-06-20T22:39:39.167420Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 2917158 entries, 4906334 to 8021121\n",
      "Data columns (total 24 columns):\n",
      " #   Column              Non-Null Count    Dtype \n",
      "---  ------              --------------    ----- \n",
      " 0   useful              2917158 non-null  int64 \n",
      " 1   funny               2917158 non-null  int64 \n",
      " 2   cool                2917158 non-null  int64 \n",
      " 3   review_count        2917158 non-null  int64 \n",
      " 4   useful_user         2917158 non-null  int64 \n",
      " 5   funny_user          2917158 non-null  int64 \n",
      " 6   cool_user           2917158 non-null  int64 \n",
      " 7   fans                2917158 non-null  int64 \n",
      " 8   average_stars       2917158 non-null  int64 \n",
      " 9   compliment_hot      2917158 non-null  int64 \n",
      " 10  compliment_more     2917158 non-null  int64 \n",
      " 11  compliment_profile  2917158 non-null  int64 \n",
      " 12  compliment_cute     2917158 non-null  int64 \n",
      " 13  compliment_list     2917158 non-null  int64 \n",
      " 14  compliment_note     2917158 non-null  int64 \n",
      " 15  compliment_plain    2917158 non-null  int64 \n",
      " 16  compliment_cool     2917158 non-null  int64 \n",
      " 17  compliment_funny    2917158 non-null  int64 \n",
      " 18  compliment_writer   2917158 non-null  int64 \n",
      " 19  compliment_photos   2917158 non-null  int64 \n",
      " 20  year                2917158 non-null  int64 \n",
      " 21  month               2917158 non-null  int64 \n",
      " 22  member_yrs          2917158 non-null  int64 \n",
      " 23  source              2917158 non-null  object\n",
      "dtypes: int64(23), object(1)\n",
      "memory usage: 556.4+ MB\n"
     ]
    }
   ],
   "source": [
    "uniques = df.nunique()\n",
    "binned = pd.concat([(df.loc[:, uniques[uniques > 20].index]\n",
    "                     .apply(pd.qcut, q=10, labels=False, duplicates='drop')),\n",
    "                    df.loc[:, uniques[uniques <= 20].index]], axis=1)\n",
    "binned.info(null_counts=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:48.721702Z",
     "start_time": "2020-06-20T22:39:47.191554Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 2917158 entries, 4906334 to 8021121\n",
      "Columns: 111 entries, source to member_yrs_15\n",
      "dtypes: object(1), uint8(110)\n",
      "memory usage: 350.5+ MB\n"
     ]
    }
   ],
   "source": [
    "dummies = pd.get_dummies(binned, \n",
    "                         columns=binned.columns.drop('source'), \n",
    "                         drop_first=True)\n",
    "dummies.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:49.237219Z",
     "start_time": "2020-06-20T22:39:48.723093Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 1701322 entries, 4906334 to 4178053\n",
      "Columns: 110 entries, useful_1 to member_yrs_15\n",
      "dtypes: uint8(110)\n",
      "memory usage: 191.5 MB\n"
     ]
    }
   ],
   "source": [
    "train_dummies = dummies[dummies.source=='train'].drop('source', axis=1)\n",
    "train_dummies.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Train set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:50.923556Z",
     "start_time": "2020-06-20T22:39:49.238342Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1701322, 110)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Cast other feature columns to float and convert to a sparse matrix.\n",
    "train_numeric = sparse.csr_matrix(train_dummies.astype(np.uint8))\n",
    "train_numeric.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:39:52.864825Z",
     "start_time": "2020-06-20T22:39:50.925657Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1701322, 10110)"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Combine sparse matrices.\n",
    "train_dtm_numeric = sparse.hstack((train_dtm, train_numeric))\n",
    "train_dtm_numeric.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:40:32.059846Z",
     "start_time": "2020-06-20T22:39:52.866020Z"
    }
   },
   "outputs": [],
   "source": [
    "sparse.save_npz(text_features_dir / 'train_dtm_numeric', \n",
    "                train_dtm_numeric)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Repeat for test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:40:34.942725Z",
     "start_time": "2020-06-20T22:40:32.062062Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1215836, 10110)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_dummies = dummies[dummies.source=='test'].drop('source', axis=1)\n",
    "test_numeric = sparse.csr_matrix(test_dummies.astype(np.int8))\n",
    "test_dtm_numeric = sparse.hstack((test_dtm, test_numeric))\n",
    "test_dtm_numeric.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:40:58.453119Z",
     "start_time": "2020-06-20T22:40:34.943972Z"
    }
   },
   "outputs": [],
   "source": [
    "sparse.save_npz(text_features_dir / 'test_dtm_numeric', test_dtm_numeric)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reload stored data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2020-06-20T22:02:02.449Z"
    }
   },
   "outputs": [],
   "source": [
    "train_dtm_numeric = sparse.load_npz(text_features_dir / 'train_dtm_numeric.npz')\n",
    "test_dtm_numeric = sparse.load_npz(text_features_dir / 'test_dtm_numeric.npz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Benchmark Accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:50.977219Z",
     "start_time": "2020-06-20T22:42:50.972604Z"
    }
   },
   "outputs": [],
   "source": [
    "accuracy, runtime = {}, {}\n",
    "predictions = test[['stars']].copy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the most frequent number of stars (=5) to predict the test set achieve an accuracy close to 51%:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:51.489449Z",
     "start_time": "2020-06-20T22:42:51.475952Z"
    }
   },
   "outputs": [],
   "source": [
    "naive_prediction = np.full_like(predictions.stars,\n",
    "                                fill_value=train.stars.mode().iloc[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:51.801719Z",
     "start_time": "2020-06-20T22:42:51.748630Z"
    }
   },
   "outputs": [],
   "source": [
    "naive_benchmark = accuracy_score(predictions.stars, naive_prediction)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:52.595624Z",
     "start_time": "2020-06-20T22:42:52.593212Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5117779042568241"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "naive_benchmark"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model Evaluation Helper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:57.625152Z",
     "start_time": "2020-06-20T22:42:57.622377Z"
    }
   },
   "outputs": [],
   "source": [
    "def evaluate_model(model, X_train, X_test, name, store=False):\n",
    "    start = time()\n",
    "    model.fit(X_train, train.stars)\n",
    "    runtime[name] = time() - start\n",
    "    predictions[name] = model.predict(X_test)\n",
    "    accuracy[result] = accuracy_score(test.stars, predictions[result])\n",
    "    if store:\n",
    "        joblib.dump(model, f'results/{result}.joblib')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multiclass Naive Bayes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:58.131555Z",
     "start_time": "2020-06-20T22:42:58.128408Z"
    }
   },
   "outputs": [],
   "source": [
    "nb = MultinomialNB()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Text Features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we train a Naive Bayes classifier using a document-term matrix produced by the CountVectorizer with default settings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:42:58.630370Z",
     "start_time": "2020-06-20T22:42:58.628383Z"
    }
   },
   "outputs": [],
   "source": [
    "result = 'nb_text'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:00.026736Z",
     "start_time": "2020-06-20T22:42:58.925479Z"
    }
   },
   "outputs": [],
   "source": [
    "evaluate_model(nb, train_dtm, test_dtm, result, store=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Accuracy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The prediction produces 64.4% accuracy on the test set, a 24.2% improvement over the benchmark:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:02.330906Z",
     "start_time": "2020-06-20T22:43:02.328364Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.6520747864021135"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "accuracy[result]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Confusion Matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:05.841915Z",
     "start_time": "2020-06-20T22:43:05.196945Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>178787</td>\n",
       "      <td>42369</td>\n",
       "      <td>8419</td>\n",
       "      <td>3193</td>\n",
       "      <td>4295</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>26795</td>\n",
       "      <td>30224</td>\n",
       "      <td>18533</td>\n",
       "      <td>4445</td>\n",
       "      <td>3025</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>12420</td>\n",
       "      <td>17233</td>\n",
       "      <td>37337</td>\n",
       "      <td>21719</td>\n",
       "      <td>6319</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>7907</td>\n",
       "      <td>5608</td>\n",
       "      <td>21599</td>\n",
       "      <td>100153</td>\n",
       "      <td>43218</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>31323</td>\n",
       "      <td>3766</td>\n",
       "      <td>6762</td>\n",
       "      <td>134072</td>\n",
       "      <td>446315</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        1      2      3       4       5\n",
       "1  178787  42369   8419    3193    4295\n",
       "2   26795  30224  18533    4445    3025\n",
       "3   12420  17233  37337   21719    6319\n",
       "4    7907   5608  21599  100153   43218\n",
       "5   31323   3766   6762  134072  446315"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stars = index = list(range(1, 6))\n",
    "pd.DataFrame(confusion_matrix(test.stars, \n",
    "                              predictions[result]),\n",
    "             columns=stars,\n",
    "             index=stars)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Text & Numeric Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:05.845364Z",
     "start_time": "2020-06-20T22:43:05.843297Z"
    }
   },
   "outputs": [],
   "source": [
    "result = 'nb_combined'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:10.443471Z",
     "start_time": "2020-06-20T22:43:05.986234Z"
    }
   },
   "outputs": [],
   "source": [
    "evaluate_model(nb, train_dtm_numeric, test_dtm_numeric, result, store=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:10.447446Z",
     "start_time": "2020-06-20T22:43:10.444431Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.6739017433272251"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "accuracy[result]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multinomial Logistic Regression"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Logistic regression also provides a multinomial training option that is faster and more accurate than the one-vs-all implementation. We use the lbfgs solver (see sklearn [documentation](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html) for details)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T22:43:30.580800Z",
     "start_time": "2020-06-20T22:43:30.578828Z"
    }
   },
   "outputs": [],
   "source": [
    "Cs = np.logspace(-5, 5, 11)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Text Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:07:29.542715Z",
     "start_time": "2020-06-20T22:46:47.149134Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "     0.00001: 34.93s | 62.02%\n",
      "     0.00010: 74.01s | 70.89%\n",
      "     0.00100: 126.02s | 73.95%\n",
      "     0.01000: 122.22s | 74.85%\n",
      "     0.10000: 125.65s | 74.80%\n",
      "     1.00000: 130.17s | 74.83%\n",
      "    10.00000: 126.39s | 74.80%\n",
      "   100.00000: 125.82s | 74.81%\n",
      "  1000.00000: 122.73s | 74.83%\n",
      " 10000.00000: 123.29s | 74.80%\n",
      "100000.00000: 126.80s | 74.80%\n"
     ]
    }
   ],
   "source": [
    "log_reg_text_accuracy = {}\n",
    "log_reg_text_runtime = []\n",
    "for i, C in enumerate(Cs):\n",
    "    start = time()\n",
    "    model = LogisticRegression(C=C,\n",
    "                               multi_class='multinomial',\n",
    "                               solver='lbfgs')\n",
    "\n",
    "    model.fit(train_dtm, train.stars)\n",
    "    log_reg_text_runtime.append(time() - start)\n",
    "    log_reg_text_accuracy[C] = accuracy_score(test.stars,\n",
    "                                              model.predict(test_dtm))\n",
    "\n",
    "    print(f'{C:12.5f}: {log_reg_text_runtime[i]:.2f}s | {log_reg_text_accuracy[C]:.2%}', flush=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:07:29.553513Z",
     "start_time": "2020-06-20T23:07:29.543848Z"
    }
   },
   "outputs": [],
   "source": [
    "pd.Series(log_reg_text_accuracy).to_csv(yelp_dir / 'logreg_text.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:07:29.569466Z",
     "start_time": "2020-06-20T23:07:29.555252Z"
    }
   },
   "outputs": [],
   "source": [
    "accuracy['lr_text'] = pd.Series(log_reg_text_accuracy).max()\n",
    "runtime['lr_text'] = np.mean(log_reg_text_runtime)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Combined Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:37:05.681465Z",
     "start_time": "2020-06-20T23:13:45.912739Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "     0.00001: 55.26s | 63.98%\n",
      "     0.00010: 99.05s | 72.94%\n",
      "     0.00100: 137.62s | 75.12%\n",
      "     0.01000: 139.11s | 75.55%\n",
      "     0.10000: 140.26s | 75.28%\n",
      "     1.00000: 138.90s | 75.32%\n",
      "    10.00000: 135.13s | 75.35%\n",
      "   100.00000: 137.76s | 75.32%\n",
      "  1000.00000: 139.09s | 75.36%\n",
      " 10000.00000: 135.01s | 75.37%\n",
      "100000.00000: 134.73s | 75.38%\n"
     ]
    }
   ],
   "source": [
    "log_reg_comb_accuracy = {}\n",
    "log_reg_comb_runtime = []\n",
    "for i, C in enumerate(Cs):\n",
    "    start = time()\n",
    "    model = LogisticRegression(C=C,\n",
    "                               multi_class='multinomial',\n",
    "                               solver='lbfgs')\n",
    "\n",
    "    model.fit(train_dtm_numeric, train.stars)\n",
    "    log_reg_comb_runtime.append(time() - start)\n",
    "    log_reg_comb_accuracy[C] = accuracy_score(test.stars,\n",
    "                                              model.predict(test_dtm_numeric))\n",
    "\n",
    "    print(f'{C:12.5f}: {log_reg_comb_runtime[i]:.2f}s | {log_reg_comb_accuracy[C]:.2%}', flush=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:37:05.685351Z",
     "start_time": "2020-06-20T23:37:05.682493Z"
    }
   },
   "outputs": [],
   "source": [
    "pd.Series(log_reg_comb_accuracy).to_csv(yelp_dir / 'logreg_combined.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:37:05.695321Z",
     "start_time": "2020-06-20T23:37:05.686557Z"
    }
   },
   "outputs": [],
   "source": [
    "accuracy['lr_comb'] = pd.Series(log_reg_comb_accuracy).max()\n",
    "runtime['lr_comb'] = np.mean(log_reg_comb_runtime)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Gradient Boosting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For illustration, we also train a lightgbm Gradient Boosting tree ensemble with default settings and multiclass objective."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:48:02.787711Z",
     "start_time": "2020-06-20T23:47:59.109776Z"
    }
   },
   "outputs": [],
   "source": [
    "lgb_train = lgb.Dataset(data=train_dtm_numeric.tocsr().astype(np.float32), \n",
    "                        label=train.stars.sub(1), \n",
    "                        categorical_feature=list(range(train_dtm_numeric.shape[1])))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:48:03.192336Z",
     "start_time": "2020-06-20T23:48:02.788712Z"
    }
   },
   "outputs": [],
   "source": [
    "lgb_test = lgb.Dataset(data=test_dtm_numeric.tocsr().astype(np.float32), \n",
    "                       label=test.stars.sub(1), \n",
    "                       reference=lgb_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-20T23:48:03.195773Z",
     "start_time": "2020-06-20T23:48:03.193461Z"
    }
   },
   "outputs": [],
   "source": [
    "param = {'objective': 'multiclass',\n",
    "         'metrics': ['multi_error'],\n",
    "         'num_class': 5}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:19:02.695721Z",
     "start_time": "2020-06-20T23:48:03.197049Z"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training until validation scores don't improve for 25 rounds\n",
      "[25]\ttraining's multi_error: 0.405759\tvalid_1's multi_error: 0.320156\n",
      "[50]\ttraining's multi_error: 0.370905\tvalid_1's multi_error: 0.297562\n",
      "[75]\ttraining's multi_error: 0.353564\tvalid_1's multi_error: 0.285789\n",
      "[100]\ttraining's multi_error: 0.34278\tvalid_1's multi_error: 0.278771\n",
      "[125]\ttraining's multi_error: 0.335184\tvalid_1's multi_error: 0.273733\n",
      "[150]\ttraining's multi_error: 0.329293\tvalid_1's multi_error: 0.269682\n",
      "[175]\ttraining's multi_error: 0.324728\tvalid_1's multi_error: 0.266682\n",
      "[200]\ttraining's multi_error: 0.320829\tvalid_1's multi_error: 0.264156\n",
      "[225]\ttraining's multi_error: 0.317401\tvalid_1's multi_error: 0.262016\n",
      "[250]\ttraining's multi_error: 0.314696\tvalid_1's multi_error: 0.259945\n",
      "[275]\ttraining's multi_error: 0.312185\tvalid_1's multi_error: 0.258219\n",
      "[300]\ttraining's multi_error: 0.3099\tvalid_1's multi_error: 0.256977\n",
      "[325]\ttraining's multi_error: 0.307957\tvalid_1's multi_error: 0.25591\n",
      "[350]\ttraining's multi_error: 0.306137\tvalid_1's multi_error: 0.254868\n",
      "[375]\ttraining's multi_error: 0.304627\tvalid_1's multi_error: 0.254025\n",
      "[400]\ttraining's multi_error: 0.302983\tvalid_1's multi_error: 0.253086\n",
      "[425]\ttraining's multi_error: 0.30154\tvalid_1's multi_error: 0.252281\n",
      "[450]\ttraining's multi_error: 0.300309\tvalid_1's multi_error: 0.251648\n",
      "[475]\ttraining's multi_error: 0.299089\tvalid_1's multi_error: 0.250989\n",
      "[500]\ttraining's multi_error: 0.297708\tvalid_1's multi_error: 0.250408\n",
      "[525]\ttraining's multi_error: 0.296714\tvalid_1's multi_error: 0.249912\n",
      "[550]\ttraining's multi_error: 0.295725\tvalid_1's multi_error: 0.249531\n",
      "[575]\ttraining's multi_error: 0.294649\tvalid_1's multi_error: 0.24918\n",
      "[600]\ttraining's multi_error: 0.293748\tvalid_1's multi_error: 0.248822\n",
      "[625]\ttraining's multi_error: 0.292762\tvalid_1's multi_error: 0.248478\n",
      "[650]\ttraining's multi_error: 0.291932\tvalid_1's multi_error: 0.248306\n",
      "[675]\ttraining's multi_error: 0.291082\tvalid_1's multi_error: 0.248\n",
      "[700]\ttraining's multi_error: 0.290352\tvalid_1's multi_error: 0.247695\n",
      "[725]\ttraining's multi_error: 0.289579\tvalid_1's multi_error: 0.247381\n",
      "[750]\ttraining's multi_error: 0.288837\tvalid_1's multi_error: 0.247131\n",
      "[775]\ttraining's multi_error: 0.288094\tvalid_1's multi_error: 0.246972\n",
      "[800]\ttraining's multi_error: 0.287377\tvalid_1's multi_error: 0.247014\n",
      "Early stopping, best iteration is:\n",
      "[776]\ttraining's multi_error: 0.288074\tvalid_1's multi_error: 0.246952\n"
     ]
    }
   ],
   "source": [
    "booster = lgb.train(params=param,\n",
    "                    train_set=lgb_train,\n",
    "                    num_boost_round=2000,\n",
    "                    early_stopping_rounds=25,\n",
    "                    valid_sets=[lgb_train, lgb_test],\n",
    "                    verbose_eval=25)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:19:02.830286Z",
     "start_time": "2020-06-21T01:19:02.696640Z"
    }
   },
   "outputs": [],
   "source": [
    "booster.save_model((yelp_dir / 'lgb_model.txt').as_posix());"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:23:53.428840Z",
     "start_time": "2020-06-21T01:19:02.831299Z"
    }
   },
   "outputs": [],
   "source": [
    "y_pred_class = booster.predict(test_dtm_numeric.astype(float))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The basic settings did not improve over the multinomial logistic regression, but further parameter tuning remains an unused option."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:23:53.507356Z",
     "start_time": "2020-06-21T01:23:53.429881Z"
    }
   },
   "outputs": [],
   "source": [
    "accuracy['lgb_comb'] = accuracy_score(test.stars, y_pred_class.argmax(1) + 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comparison"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:30:47.685215Z",
     "start_time": "2020-06-21T01:30:47.678355Z"
    }
   },
   "outputs": [],
   "source": [
    "model_map = {'nb_combined': 'Naive Bayes',\n",
    "             'lr_comb': 'Logistic Regression',\n",
    "             'lgb_comb': 'LightGBM'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T02:05:08.492311Z",
     "start_time": "2020-06-21T02:05:08.490190Z"
    }
   },
   "outputs": [],
   "source": [
    "accuracy_ = {model_map[k]: v for k, v in accuracy.items() if model_map.get(k)}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T02:05:09.077394Z",
     "start_time": "2020-06-21T02:05:09.070418Z"
    }
   },
   "outputs": [],
   "source": [
    "log_reg_text = pd.read_csv(yelp_dir / 'logreg_text.csv',\n",
    "                       index_col=0,\n",
    "                       squeeze=True)\n",
    "log_reg_combined = pd.read_csv(yelp_dir / 'logreg_combined.csv',\n",
    "                       index_col=0,\n",
    "                       squeeze=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T02:05:42.706220Z",
     "start_time": "2020-06-21T02:05:42.145823Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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PcLDwzl8+HCW3zVffvklgYGBLFq0iFmzZrFx40ZsNluW6y9LS0tjwIABBAcHEx4ezueff8706dPZvHkzANu2beOZZ55h8eLFdO/enRkzZtzU5xYQEICHhwdbt24FYOXKlQQGBuLm5pZjHBEREaxcuZLFixczf/58kpKSHO1mdV7zwvbt2/nyyy/56aefiIuL4+eff76mzIYNGxgzZgzLli2jYcOGjtsIhg8fTqdOnVi2bBmjR49my5YteRKjFDzqQReRDObNm0e7du0oU6YMZcqUoVq1anz33Xd4eHjQqlUrKleuDEC/fv0A+OqrrzJdv379+mz306hRI8eXbN++fdm4cSNfffUV+/btIzY2loYNG3L69GmioqJ47LHHAKhcuTIREREAPPHEE3z33Xe0bduWBQsWMHz48Ez306FDB0fi3aNHD959990bqg/QuXNnunbtyptvvsmqVasIDAzEYrE4tq9Zs4ZBgwbh7u4O2IfAvfzyy8TExODm5ua42v/II48wduxYANauXUt8fLzjfAGYTKabvp9NREQyt2bNGubNm4fJZMLDw4OgoCDmzJnD7bffTq1atahXrx4A3bp1y/Q+8k6dOvHKK6/Qtm1bWrZsyfPPP5/t/tatW8ewYcMAKFmypGMk2dXSX4z+7bffGDZsGO3atcPLywuw3+N+9uxZ1q1bB9hHa5UrV46YmBgA2rZtC8A999yDv7+/o93KlStTtWpVIPvvmg4dOjBixAi2bdtGixYtGD16NGazOcv1l+3bt4+LFy/ywAMPAFCxYkUeeOABfvvtN5o3b06VKlUICAgAoH79+vz444/Znq/sdO3alaVLl9KwYUMWL17MG2+8wezZs3OMIzExkQ4dOjh6xXv06EFYWFi25zUvtG7dGg8PD8A+Iu/yLRHp3XHHHVSqVAmwn69Vq1aRmJjItm3b+OabbwCoVasW99xzT57EKAWPEnQRcUhOTmbJkiV4eHgQGBgIQFJSEt988w3PPfccJpPJUfbChQvExcVhsVgyXW8ymTAMw7E+NTU1w75KlCjheD916lS2bdtGjx49aN68OWlpaRiG4Ujg07e/Z88eqlSpQufOnZk+fTp//vknycnJNGvWLNNjSp9I22w2R5vXWx/A19eX+vXrs2bNGhYvXszIkSM5depUhnbTx2iz2RzHm/4cAI7922w2WrRowfvvv+/Y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tIq7i/pDw5qkJvV0dhhuxzQLTiivIk6RV1hMNV9vZ4chckdtSrfRrGEN6tao5uxQRESkCtIIuoiIVAoV5+LusnIK2PPvLDpr9FxExCWlpqYyZ86c654fPXo0BQUFFT7usWPHsFqtvyc0B42gi0cZPny4s0MQERE39dXhTOwGPKLrz0XEne1dCmn/vL3HbDkIWsTf3mOWw7x585x27t9SgS4eZcGCBc4OQURE3NTGdBtBd5l5IMTi7FBERNxKXl4eL730EmfOnKGwsJBJkyaxfPlyTp06RXFxMU899RQ9evTAarXSpEkTjhw5QvXq1WnTpg1btmzh8uXLLFq0CIC9e/cyZMgQsrOz+ctf/kKnTp3o3Lkza9eu5dVXX8VsNnP69GlsNhtJSUncf//9rF27lvfeew8vLy9at27Niy++iM1m48UXX8QwDIKDg2/ba1WBLh6ldevW7N6929lhiIiImykqtvPV4UwebVoXLy+Ts8MREblzWsRX+mj3smXLaNiwIfPmzePw4cNs2LCBWrVqMXv2bLKzs4mJiaFt27YANG/enFdeeYWnn36aatWqsXjxYiZMmMDOnTsB8Pf3Z8GCBVy8eJH+/fvToUOHa8519913M23aNFasWMHy5csZM2YMb7zxBh999BH+/v6MGzeOrVu3smXLFnr16kVcXBxr1qxh6dKlt+W16hp08Sh79uxxdggiIlIGdrudKVOmMGDAAKxWKydPnrym/bvvviMhIYH4+Hief/558vPzKSwsZNy4cSQkJBAbG8uXX35ZafGmnbrEz1cKdXs1EZE74Mcff6RFixYANG7cmMzMTB588EEAAgICiIiI4NSpUwDcf//9ANSoUYPIyEjHv/Pz84GSATuTyURQUBCBgYFcunTpmnM1bdoUgPr161NQUMC///1vLl68yDPPPIPVauXYsWOcOnWKI0eO0Lx5cwBatWp1216rRtBFRETE5WzYsIGCggKWL1/O3r17SUpK4q233gLAMAwmT57Mf//3fxMaGkpKSgqnT58mLS0Ni8XC7NmzycrKol+/fjz66KOVEu/GdBveXiaio27fNEcRESkRERHB/v376dKlC6dOneKzzz7DbDbTtWtXsrOzOXz4MCEhIWU61v79+wHIzMwkNzeXWrVqXdNuMl07CyokJIQGDRqwaNEifH19SU1NpWnTpvz444+kpaVx3333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LFy4kOHDh3PkyBFmz57N+++/T+fOnVm3bh0//PADmzdvJiUlhWXLlnH06FF69uzJl19+SXFxMV9//TUPPfSQinMRERERqRQaQRcRp/v555/ZvHkzFy9eJDk5mezsbP75z39y4cIFIiIiAHjyyScBSn3u13697mVISIijuK5Xrx7Tp0+nevXqnDt3jlatWnH8+HGaN2+Ot7c3/v7+vPLKKwA8+OCDbNmyhdTUVJ599tk7+tpFRERERK7SCLqION2qVav405/+xKJFi1i4cCErVqxg69at+Pn5ceLECaBkAbkvvviCunXrXvec2WwmMzMTgB9++MFxXC+v/32Le+WVV5gxYwZJSUnUrVsXwzAIDw/nhx9+wG63U1hYyFNPPUVBQQFxcXGkpKRw4cIF7rvvvkrLg4iIiIh4No2gi4jTpaSk8Pe//93x2N/fn8cee4w6deowadIkvLy8CA4OZujQodSrV++658xmM9OmTaNBgwbUrVu31HP07duXuLg4atSoQZ06dbDZbDRt2pTo6Gji4+Ox2+3Ex8djNpt54IEHOHnyZKkj9CIiIiIid4rugy4i8htXi/WFCxcSEBDg7HBtscreAAAEp0lEQVRERERKtWPHDl544QUiIyMByMnJISQkhDlz5vzu9VPeeOMN6tSpQ3x8/C23PXjwIF9++SWjRo0q8/Hz8/NZtWoV/fv3JzU1lZo1a/Loo4/+npBF3IKmuIuI/MqpU6fo168fffv2VXEuIiIur23btiQnJ5OcnExqaiq+vr5s3LixUmNo2rRpuYpzKFnINSUlBYCYmBgV5yL/n6a4i4j8SqNGjfjkk0+cHYaIiEi5FRQUYLPZqFmzJnPnzmXnzp0YhsHQoUPp3r073333HVOnTuWuu+4iKCgIPz8/Ro0axZgxY1ixYgUAcXFxvP76645jFhcXM2XKFH766SeysrLo0KEDL7zwAhMnTuTSpUtcunSJp59+mjVr1jBmzBgmTZoElIzm//jjj2zbto2PPvqI9evXU1RURGBgIG+88QZvv/02R48eZf78+RiG4RitT0pKYvfu3QD06tWLIUOGMHHiRMxmM6dPn8Zms5GUlMT9999f+QkWqQQaQRcRERERqaK2b9+O1WqlR48exMTE0LVrVwoKCsjIyGDZsmW8//77vP3221y+fJlXX32VpKQk3n//fe65554yHf/s2bO0aNGChQsXsnTpUpYuXepoa9u2LcuWLaNGjRpAyY/cycnJLFy4EIvFwj/+8Q/8/Py4dOkS7733Hh9++CFFRUXs37+fESNGEBkZec3I+6ZNm8jIyGDFihV8+OGHfPrppxw6dAiAu+++m4ULF2K1Wlm+fPltzKCIa9EIuoiIiIhIFdW2bVvmzZtHVlYWw4YNIyQkhMOHD/P9999jtVoBKCoq4syZM9hsNqKiogBo3bo1a9asue54v12eymKxsH//frZv305AQAAFBQWOtrCwsOv2Ly4uZvTo0fTp04eOHTsC4Ovry5gxY6hevTo//fQTRUVFpb6WY8eO0aZNG0wmE76+vjzwwAMcO3YMKJlGD1C/fn327NlT3jSJVBkaQRcRERERqeJq1arF7NmzeeWVV6hTpw4PPfQQycnJLFmyhO7duxMSEkL9+vU5evQoAPv27QPAz8+PCxcuUFxczOXLl8nIyLjmuKmpqQQGBjJ37lyGDRtGXl6eo4g3mUzXbGsYBpMmTaJly5Y88cQTAKSnp7Nhwwb+67/+i8mTJ2O32zEMAy8vL+x2+zX7R0REOKa3FxYWkpaWRmhoaKnnEnFXGkEXEREREXEDkZGRWK1WNm3aRIMGDUhISCA3N5cuXboQEBDAq6++yqRJk6hevTq+vr7Uq1eP4OBgHn74YWJjY7nnnnscBfFV7dq1Y8yYMezevRt/f39CQ0Ox2Wylnn/dunWsX7+ec+fO8dVXXwHw6quv4u/vT0xMDGazmeDgYGw2Gy1btqSwsJDZs2dTrVo1AB555BG+/fZbBgwYQGFhId26ddO15uJxdJs1EREREREP8MEHH9C9e3dq167NvHnz8PX1Lffq6yJyZ2kEXURERETEAwQFBTFs2DCqV69OYGAgSUlJzg5JRH5DI+giIiIiIiIiLkCLxImIiIiIiIi4ABXoIiIiIiIiIi5ABbqIiIiIiIiIC1CBLiIiIiIiIuICVKCLiIiIiIiIuID/B2Y5q+X0WAH5AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 1008x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(ncols=2, figsize=(14, 4))\n",
    "pd.Series(accuracy_).sort_values().plot.barh(\n",
    "    ax=axes[0], xlim=(.45, .75), title='Accuracy by Model')\n",
    "axes[0].axvline(naive_benchmark, ls='--', lw=1, c='k')\n",
    "\n",
    "\n",
    "log_reg = (log_reg_text.to_frame('text')\n",
    "           .join(log_reg_combined.to_frame('combined')))\n",
    "log_reg.plot(logx=True,\n",
    "             ax=axes[1],\n",
    "             title='Logistic Regression - Model Tuning')\n",
    "axes[1].set_xlabel('Regularization')\n",
    "axes[1].set_ylabel('Accuracy')\n",
    "axes[0].set_xlabel('Accuracy')\n",
    "sns.despine()\n",
    "fig.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Textblob for Sentiment Analysis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:33:15.816005Z",
     "start_time": "2020-06-21T01:33:15.771890Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "It's good to see new restaurants in Henderson along Stephanie Street, and judging by the packed parking lot a lot of people seem to like Miller's Ale House. I can't say that I'm a fan. I'll agree with Ashley B's review that it's better than Chili's and far better than suffering through Applebees, but it's really just a ho-hum nothing special chain restaurant with TV's plastered everywhere, and a boring menu of the same tired classics that can be easily prepared by a bunch of distracted teenagers working the kitchen. \n",
      "\n",
      "If you're hungry and the parking lot is not jammed and you can't decide on what to eat at least you can shut your stomach up if you stop here. But if you want something different or original remember this is a chain....you won't find what you're craving here. \n",
      "\n",
      "2 Stars...as in I was so underwhelmed by the place I almost fell asleep writing this one. Yawn!\n"
     ]
    }
   ],
   "source": [
    "sample_review = train.text.sample(1).iloc[0]\n",
    "print(sample_review)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:33:15.953592Z",
     "start_time": "2020-06-21T01:33:15.921212Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.11637265512265516"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Polarity ranges from -1 (most negative) to 1 (most positive).\n",
    "TextBlob(sample_review).sentiment.polarity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:33:16.084637Z",
     "start_time": "2020-06-21T01:33:16.081057Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "# Define a function that accepts text and returns the polarity.\n",
    "def detect_sentiment(text):\n",
    "    return TextBlob(text).sentiment.polarity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:46:35.286143Z",
     "start_time": "2020-06-21T01:33:16.252155Z"
    }
   },
   "outputs": [],
   "source": [
    "train['sentiment'] = train.text.apply(detect_sentiment)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:46:35.421683Z",
     "start_time": "2020-06-21T01:46:35.287184Z"
    }
   },
   "outputs": [],
   "source": [
    "sample_reviews = train[['stars', 'text']].sample(100000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:22.961955Z",
     "start_time": "2020-06-21T01:46:35.422792Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "# Create a new DataFrame column for sentiment (Warning: SLOW!).\n",
    "sample_reviews['sentiment'] = sample_reviews.text.apply(detect_sentiment)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:23.391637Z",
     "start_time": "2020-06-21T01:47:22.963037Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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O5BEj4rwuK0VOtEPV36fPHky3nnnHbXTIHIxbPWNWVNL5paomIn6do+4MVZg5J7dKmaivjXzi5yf1b6bcHftVP2OgihQlMwtQSu0CvgiAdwoDoFeJIAbxUHtIuEJCwWRgv45959qp6AZLBI3aLlIACwURETUABYKIiLyiIWCiIg88stRLmfOnMHkyZPVToOIyKecOXNGMu6X3WOJiKjl8NETERF5xEJBREQesVAQEZFHLBREROQRCwUREXnEQkFERB6xULSAAwcOIDk5uV58586dmDJlChISErB582YVMlPO9evXkZ6ejmnTpiEuLg47driuLxBI5wIAHA4HMjIykJiYiOnTp+Pbb7912R9o56OqqgojR47EiRMnXOKBdh4mTZqE5ORkJCcnIyMjw2Wfps+FSM2ybt068aGHHhLj4+Nd4jabTRw9erR46dIl8dq1a+LkyZPFH3/8UaUs5VdYWChmZWWJoiiKFy5cEEeOHOncF2jnQhRFcfv27eLChQtFURTFzz//XHziiSec+wLtfNhsNnHOnDni2LFjxePHj7vEA+k8XL16VXzkkUck92n9XPCOopnCwsKwevXqevETJ04gLCwM7dq1g9FoRExMDEpLS1XIUBnjx4/HU0895dw2GAzOz4F2LgBg9OjRWL58OQDghx9+QKdOnZz7Au18rFy5EomJibj11ltd4oF2HioqKnDlyhXMnDkTKSkpKC8vd+7T+rlgoWimcePGIUhivV+LxQKz2ezcDgkJgcViUTI1RYWEhMBkMsFiseC3v/0tfve73zn3Bdq5qBMUFIRnnnkGy5cvx7hx45zxQDof77zzDkJDQxEbG1tvXyCdBwC45ZZbkJqaildffRVLly7FggULYP/P+uFaPxcsFDIxmUywWq3ObavV6vKN4I/Onj2LlJQUPPLII5g48cb8+oF4LuqsXLkS27Ztw7PPPouamhoAgXU+3n77bXz66adITk7G4cOH8cwzz+DcuXMAAus8AEB4eDgefvhh6HQ6hIeHo3379j5zLlgoZBIREYHTp0/j0qVLsNlsKC0txeDBg9VOSzbnz5/HzJkzkZ6ejri4OJd9gXYuAODvf/87Xn75ZQBAcHAwdDqd83FcIJ2PN954A6+//jry8/PRv39/rFy5Ep07dwYQWOcBAAoLC7FixQoAQGVlJSwWi8+cC7+cPVZNRUVFqKmpQUJCAhYuXIjU1FSIoogpU6agS5cuaqcnm7Vr1+Knn35Cbm4ucnNzAQDx8fG4cuVKwJ0LABg7diwyMjIwffp02O12LFq0CB999FFAfm/cLFB/RuLi4pCRkYGkpCTodDpkZ2fjgw8+8IlzwdljiYjIIz56IiIij1goiIjIIxYKIiLyiIWCiIg8YqEgIiKPWCiIZPD666+rnQJRi2GhIJJBXl6e2ikQtRgOuCNqppMnTyIjIwNBQUEwGAy49957cfnyZWRmZmLBggX4wx/+gOrqaly8eBHx8fGYNm0akpOT0aFDB/z0009YsmQJFi1a5Gz/pz/9SVODrYhYKIia6dNPP8WAAQOwcOFClJaWomPHjnj99deRmZmJQ4cO4cEHH8TYsWNRWVmJ5ORkTJs2DQAwceJEjBkzBm+88YZL+8uXL7NQkKbw0RNRM8XFxaFDhw54/PHH8cYbb7hMsd6pUycUFxdjwYIFyMvLc84WCtROEtdQeyItYKEgaqYdO3YgJiYGGzduxPjx4/HKK6+gbmac9evXIyoqCs8//zzGjx+Pn8+Yo9Pp3LYn0hI+eiJqpoEDByI9PR2rV6+GXq9HRkYGvv/+eyxYsABxcXHIzMxEUVER2rdvD4PBAJvN1mB7Ii3hpIBEROQRHz0REZFHLBREROQRCwUREXnEQkFERB6xUBARkUcsFERE5BELBRERefT/AczHVSwFxDEvAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Box plot of sentiment grouped by stars\n",
    "sns.boxenplot(x='stars', y='sentiment', data=train);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:23.394501Z",
     "start_time": "2020-06-21T01:47:23.392648Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "# Widen the column display.\n",
    "pd.set_option('max_colwidth', 500)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:23.415900Z",
     "start_time": "2020-06-21T01:47:23.395803Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2495072                                                  TERRIBLE!! I Ordered And They Just Cancelled My Order Because they \"don't deliver to my hotel\" no notice or anything just cancelled!!! I Was Waiting For My\\nOrder for about an hour!\n",
       "4807229                                                                                                              Don't bother to give them a call they did a no show for an estimate not even a phone call to let me know horrible service\n",
       "4379860                                                                                                      horrible, horrible, horrible.  food, service price.  it's an overpriced tourist trap.  Pease do yourself a favor, go to in n out.\n",
       "2941002                                                                                                           Well after my miserable experience they came with the rest of my furniture today. All broken and cracked! Dump!!!!!!!!!!!!!!\n",
       "2785241    This is probably the worst experience I have had at a restaurant.  Waited 10 minutes for even a server to come take my drink order.  Paid $15 for a crappy breakfast.  \\n\\nI will never eat at this California pizza kitchen again.\n",
       "Name: text, dtype: object"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Reviews with most negative sentiment\n",
    "train[train.sentiment == -1].text.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:23.425332Z",
     "start_time": "2020-06-21T01:47:23.417267Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "255057    Appointment set through Fidelity Home Warranty. Ken came out within a couple of hours. The capacitor was bad on one of my units and replaced immediately. Thank you Fidelity and Ken at Lee Collins Air.\n",
       "Name: text, dtype: object"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Negative sentiment in a 5-star review\n",
    "train.loc[(train.stars == 5) & (train.sentiment < -0.3), 'text'].head(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:23.437225Z",
     "start_time": "2020-06-21T01:47:23.426564Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5373197    The food wasn't that great and the service was okay. We should have just gone to our go to spot Baby Stacks. The steak and eggs had no flavor and the potatoes were room temperature. I guess this is what happens when you want breakfast for dinner. The bill was $46 which is fine but if the food was actually good I don't think I would be as ann\n",
       "Name: text, dtype: object"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Positive sentiment in a 1-star review\n",
    "train.loc[(train.stars == 1) & (train.sentiment > 0.5), 'text'].head(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-21T01:47:23.447787Z",
     "start_time": "2020-06-21T01:47:23.438154Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "# Reset the column display width.\n",
    "pd.reset_option('max_colwidth')"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": true,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "316px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
